annotate src/share/vm/c1/c1_LinearScan.cpp @ 13212:eb03a7335eb0

Use fixed instead of virtual register for target in far foreign call, since the register allocator does not support virtual registers to be used at call sites.
author Christian Wimmer <christian.wimmer@oracle.com>
date Mon, 02 Dec 2013 14:20:32 -0800
parents a905d33ce13a
children de6a9e811145
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
6842
b9a9ed0f8eeb 7197424: update copyright year to match last edit in jdk8 hotspot repository
mikael
parents: 6739
diff changeset
2 * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
25 #include "precompiled.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
26 #include "c1/c1_CFGPrinter.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
27 #include "c1/c1_CodeStubs.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
28 #include "c1/c1_Compilation.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
29 #include "c1/c1_FrameMap.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
30 #include "c1/c1_IR.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
31 #include "c1/c1_LIRGenerator.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
32 #include "c1/c1_LinearScan.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
33 #include "c1/c1_ValueStack.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
34 #include "utilities/bitMap.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
35 #ifdef TARGET_ARCH_x86
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
36 # include "vmreg_x86.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
37 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
38 #ifdef TARGET_ARCH_sparc
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
39 # include "vmreg_sparc.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
40 #endif
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
41 #ifdef TARGET_ARCH_zero
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
42 # include "vmreg_zero.inline.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1819
diff changeset
43 #endif
2192
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
44 #ifdef TARGET_ARCH_arm
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
45 # include "vmreg_arm.inline.hpp"
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
46 #endif
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
47 #ifdef TARGET_ARCH_ppc
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
48 # include "vmreg_ppc.inline.hpp"
b92c45f2bc75 7016023: Enable building ARM and PPC from src/closed repository
bobv
parents: 2081
diff changeset
49 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
53
a61af66fc99e Initial load
duke
parents:
diff changeset
54 static LinearScanStatistic _stat_before_alloc;
a61af66fc99e Initial load
duke
parents:
diff changeset
55 static LinearScanStatistic _stat_after_asign;
a61af66fc99e Initial load
duke
parents:
diff changeset
56 static LinearScanStatistic _stat_final;
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 static LinearScanTimers _total_timer;
a61af66fc99e Initial load
duke
parents:
diff changeset
59
a61af66fc99e Initial load
duke
parents:
diff changeset
60 // helper macro for short definition of timer
a61af66fc99e Initial load
duke
parents:
diff changeset
61 #define TIME_LINEAR_SCAN(timer_name) TraceTime _block_timer("", _total_timer.timer(LinearScanTimers::timer_name), TimeLinearScan || TimeEachLinearScan, Verbose);
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 // helper macro for short definition of trace-output inside code
a61af66fc99e Initial load
duke
parents:
diff changeset
64 #define TRACE_LINEAR_SCAN(level, code) \
a61af66fc99e Initial load
duke
parents:
diff changeset
65 if (TraceLinearScanLevel >= level) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
66 code; \
a61af66fc99e Initial load
duke
parents:
diff changeset
67 }
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
70
a61af66fc99e Initial load
duke
parents:
diff changeset
71 #define TIME_LINEAR_SCAN(timer_name)
a61af66fc99e Initial load
duke
parents:
diff changeset
72 #define TRACE_LINEAR_SCAN(level, code)
a61af66fc99e Initial load
duke
parents:
diff changeset
73
a61af66fc99e Initial load
duke
parents:
diff changeset
74 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 // Map BasicType to spill size in 32-bit words, matching VMReg's notion of words
a61af66fc99e Initial load
duke
parents:
diff changeset
77 #ifdef _LP64
12969
9acbfe04b5c3 8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents: 8860
diff changeset
78 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 2, 1, 2, 1, -1};
0
a61af66fc99e Initial load
duke
parents:
diff changeset
79 #else
12969
9acbfe04b5c3 8026495: JVM Crashes when started with -XX:+DTraceMethodProbes on Solaris x86_64
iveresov
parents: 8860
diff changeset
80 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1, 1, 1, -1};
0
a61af66fc99e Initial load
duke
parents:
diff changeset
81 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
82
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84 // Implementation of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
85
a61af66fc99e Initial load
duke
parents:
diff changeset
86 LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
87 : _compilation(ir->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
88 , _ir(ir)
a61af66fc99e Initial load
duke
parents:
diff changeset
89 , _gen(gen)
a61af66fc99e Initial load
duke
parents:
diff changeset
90 , _frame_map(frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
91 , _num_virtual_regs(gen->max_virtual_register_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
92 , _has_fpu_registers(false)
a61af66fc99e Initial load
duke
parents:
diff changeset
93 , _num_calls(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
94 , _max_spills(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
95 , _unused_spill_slot(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
96 , _intervals(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
97 , _new_intervals_from_allocation(new IntervalList())
a61af66fc99e Initial load
duke
parents:
diff changeset
98 , _sorted_intervals(NULL)
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
99 , _needs_full_resort(false)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
100 , _lir_ops(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
101 , _block_of_op(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
102 , _has_info(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
103 , _has_call(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
104 , _scope_value_cache(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
105 , _interval_in_loop(0, 0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
106 , _cached_blocks(*ir->linear_scan_order())
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
107 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
108 , _fpu_stack_allocator(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
109 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
110 {
a61af66fc99e Initial load
duke
parents:
diff changeset
111 assert(this->ir() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
112 assert(this->compilation() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
113 assert(this->gen() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
114 assert(this->frame_map() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116
a61af66fc99e Initial load
duke
parents:
diff changeset
117
a61af66fc99e Initial load
duke
parents:
diff changeset
118 // ********** functions for converting LIR-Operands to register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
119 //
a61af66fc99e Initial load
duke
parents:
diff changeset
120 // Emulate a flat register file comprising physical integer registers,
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // physical floating-point registers and virtual registers, in that order.
a61af66fc99e Initial load
duke
parents:
diff changeset
122 // Virtual registers already have appropriate numbers, since V0 is
a61af66fc99e Initial load
duke
parents:
diff changeset
123 // the number of physical registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
124 // Returns -1 for hi word if opr is a single word operand.
a61af66fc99e Initial load
duke
parents:
diff changeset
125 //
a61af66fc99e Initial load
duke
parents:
diff changeset
126 // Note: the inverse operation (calculating an operand for register numbers)
a61af66fc99e Initial load
duke
parents:
diff changeset
127 // is done in calc_operand_for_interval()
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129 int LinearScan::reg_num(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
130 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
131
a61af66fc99e Initial load
duke
parents:
diff changeset
132 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 assert(opr->vreg_number() >= nof_regs, "found a virtual register with a fixed-register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
134 return opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
135 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
136 return opr->cpu_regnr();
a61af66fc99e Initial load
duke
parents:
diff changeset
137 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
138 return opr->cpu_regnrLo();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
139 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
140 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
141 return opr->fpu_regnr() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
142 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
143 return opr->fpu_regnrLo() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
144 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
145 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
146 return opr->fpu_regnr() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
147 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
148 return opr->fpu_regnrLo() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
149 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
150 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
151 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154
a61af66fc99e Initial load
duke
parents:
diff changeset
155 int LinearScan::reg_numHi(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
156 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
160 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
161 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
162 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
163 return opr->cpu_regnrHi();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
164 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
165 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
166 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
169 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
170 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
171 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
172 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
173 return opr->fpu_regnrHi() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
174 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
176 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
179
a61af66fc99e Initial load
duke
parents:
diff changeset
180
a61af66fc99e Initial load
duke
parents:
diff changeset
181 // ********** functions for classification of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 bool LinearScan::is_precolored_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
184 return i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
186
a61af66fc99e Initial load
duke
parents:
diff changeset
187 bool LinearScan::is_virtual_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 return i->reg_num() >= LIR_OprDesc::vreg_base;
a61af66fc99e Initial load
duke
parents:
diff changeset
189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
190
a61af66fc99e Initial load
duke
parents:
diff changeset
191 bool LinearScan::is_precolored_cpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
192 return i->reg_num() < LinearScan::nof_cpu_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
194
a61af66fc99e Initial load
duke
parents:
diff changeset
195 bool LinearScan::is_virtual_cpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
196 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
197 return i->reg_num() >= LIR_OprDesc::vreg_base;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
198 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
199 return i->reg_num() >= LIR_OprDesc::vreg_base && (i->type() != T_FLOAT && i->type() != T_DOUBLE);
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
200 #endif // __SOFTFP__ or E500V2
0
a61af66fc99e Initial load
duke
parents:
diff changeset
201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
202
a61af66fc99e Initial load
duke
parents:
diff changeset
203 bool LinearScan::is_precolored_fpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
204 return i->reg_num() >= LinearScan::nof_cpu_regs && i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
205 }
a61af66fc99e Initial load
duke
parents:
diff changeset
206
a61af66fc99e Initial load
duke
parents:
diff changeset
207 bool LinearScan::is_virtual_fpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
208 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
209 return false;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
210 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
211 return i->reg_num() >= LIR_OprDesc::vreg_base && (i->type() == T_FLOAT || i->type() == T_DOUBLE);
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
212 #endif // __SOFTFP__ or E500V2
0
a61af66fc99e Initial load
duke
parents:
diff changeset
213 }
a61af66fc99e Initial load
duke
parents:
diff changeset
214
a61af66fc99e Initial load
duke
parents:
diff changeset
215 bool LinearScan::is_in_fpu_register(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
216 // fixed intervals not needed for FPU stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
217 return i->reg_num() >= nof_regs && pd_first_fpu_reg <= i->assigned_reg() && i->assigned_reg() <= pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
219
a61af66fc99e Initial load
duke
parents:
diff changeset
220 bool LinearScan::is_oop_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // fixed intervals never contain oops
a61af66fc99e Initial load
duke
parents:
diff changeset
222 return i->reg_num() >= nof_regs && i->type() == T_OBJECT;
a61af66fc99e Initial load
duke
parents:
diff changeset
223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
224
a61af66fc99e Initial load
duke
parents:
diff changeset
225
a61af66fc99e Initial load
duke
parents:
diff changeset
226 // ********** General helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 // compute next unused stack index that can be used for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
229 int LinearScan::allocate_spill_slot(bool double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
230 int spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 if (double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
232 if ((_max_spills & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // alignment of double-word values
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // the hole because of the alignment is filled with the next single-word value
a61af66fc99e Initial load
duke
parents:
diff changeset
235 assert(_unused_spill_slot == -1, "wasting a spill slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
236 _unused_spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
237 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
238 }
a61af66fc99e Initial load
duke
parents:
diff changeset
239 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
240 _max_spills += 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 } else if (_unused_spill_slot != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // re-use hole that was the result of a previous double-word alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
244 spill_slot = _unused_spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
245 _unused_spill_slot = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
249 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251
a61af66fc99e Initial load
duke
parents:
diff changeset
252 int result = spill_slot + LinearScan::nof_regs + frame_map()->argcount();
a61af66fc99e Initial load
duke
parents:
diff changeset
253
a61af66fc99e Initial load
duke
parents:
diff changeset
254 // the class OopMapValue uses only 11 bits for storing the name of the
a61af66fc99e Initial load
duke
parents:
diff changeset
255 // oop location. So a stack slot bigger than 2^11 leads to an overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
256 // that is not reported in product builds. Prevent this by checking the
a61af66fc99e Initial load
duke
parents:
diff changeset
257 // spill slot here (altough this value and the later used location name
a61af66fc99e Initial load
duke
parents:
diff changeset
258 // are slightly different)
a61af66fc99e Initial load
duke
parents:
diff changeset
259 if (result > 2000) {
a61af66fc99e Initial load
duke
parents:
diff changeset
260 bailout("too many stack slots used");
a61af66fc99e Initial load
duke
parents:
diff changeset
261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
262
a61af66fc99e Initial load
duke
parents:
diff changeset
263 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
265
a61af66fc99e Initial load
duke
parents:
diff changeset
266 void LinearScan::assign_spill_slot(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // assign the canonical spill slot of the parent (if a part of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // is already spilled) or allocate a new spill slot
a61af66fc99e Initial load
duke
parents:
diff changeset
269 if (it->canonical_spill_slot() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
270 it->assign_reg(it->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
271 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
272 int spill = allocate_spill_slot(type2spill_size[it->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
273 it->set_canonical_spill_slot(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
274 it->assign_reg(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
277
a61af66fc99e Initial load
duke
parents:
diff changeset
278 void LinearScan::propagate_spill_slots() {
a61af66fc99e Initial load
duke
parents:
diff changeset
279 if (!frame_map()->finalize_frame(max_spills())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
280 bailout("frame too large");
a61af66fc99e Initial load
duke
parents:
diff changeset
281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
282 }
a61af66fc99e Initial load
duke
parents:
diff changeset
283
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // create a new interval with a predefined reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // (only used for parent intervals that are created during the building phase)
a61af66fc99e Initial load
duke
parents:
diff changeset
286 Interval* LinearScan::create_interval(int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
287 assert(_intervals.at(reg_num) == NULL, "overwriting exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
288
a61af66fc99e Initial load
duke
parents:
diff changeset
289 Interval* interval = new Interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
290 _intervals.at_put(reg_num, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // assign register number for precolored intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
293 if (reg_num < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
294 interval->assign_reg(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
296 return interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
298
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // assign a new reg_num to the interval and append it to the list of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // (only used for child intervals that are created during register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
301 void LinearScan::append_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
302 it->set_reg_num(_intervals.length());
a61af66fc99e Initial load
duke
parents:
diff changeset
303 _intervals.append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
304 _new_intervals_from_allocation->append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
306
a61af66fc99e Initial load
duke
parents:
diff changeset
307 // copy the vreg-flags if an interval is split
a61af66fc99e Initial load
duke
parents:
diff changeset
308 void LinearScan::copy_register_flags(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
309 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::byte_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
310 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::byte_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
312 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::callee_saved)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
313 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::callee_saved);
a61af66fc99e Initial load
duke
parents:
diff changeset
314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
315
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // Note: do not copy the must_start_in_memory flag because it is not necessary for child
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // intervals (only the very beginning of the interval must be in memory)
a61af66fc99e Initial load
duke
parents:
diff changeset
318 }
a61af66fc99e Initial load
duke
parents:
diff changeset
319
a61af66fc99e Initial load
duke
parents:
diff changeset
320
a61af66fc99e Initial load
duke
parents:
diff changeset
321 // ********** spill move optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
322 // eliminate moves from register to stack if stack slot is known to be correct
a61af66fc99e Initial load
duke
parents:
diff changeset
323
a61af66fc99e Initial load
duke
parents:
diff changeset
324 // called during building of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
325 void LinearScan::change_spill_definition_pos(Interval* interval, int def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
326 assert(interval->is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
327
a61af66fc99e Initial load
duke
parents:
diff changeset
328 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
329 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
330 assert(interval->spill_definition_pos() == -1, "must no be set before");
a61af66fc99e Initial load
duke
parents:
diff changeset
331 interval->set_spill_definition_pos(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
332 interval->set_spill_state(oneDefinitionFound);
a61af66fc99e Initial load
duke
parents:
diff changeset
333 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
334
a61af66fc99e Initial load
duke
parents:
diff changeset
335 case oneDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
336 assert(def_pos <= interval->spill_definition_pos(), "positions are processed in reverse order when intervals are created");
a61af66fc99e Initial load
duke
parents:
diff changeset
337 if (def_pos < interval->spill_definition_pos() - 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
338 // second definition found, so no spill optimization possible for this interval
a61af66fc99e Initial load
duke
parents:
diff changeset
339 interval->set_spill_state(noOptimization);
a61af66fc99e Initial load
duke
parents:
diff changeset
340 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // two consecutive definitions (because of two-operand LIR form)
a61af66fc99e Initial load
duke
parents:
diff changeset
342 assert(block_of_op_with_id(def_pos) == block_of_op_with_id(interval->spill_definition_pos()), "block must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
344 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
345
a61af66fc99e Initial load
duke
parents:
diff changeset
346 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
347 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
348 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
349
a61af66fc99e Initial load
duke
parents:
diff changeset
350 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
351 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
352 }
a61af66fc99e Initial load
duke
parents:
diff changeset
353 }
a61af66fc99e Initial load
duke
parents:
diff changeset
354
a61af66fc99e Initial load
duke
parents:
diff changeset
355 // called during register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
356 void LinearScan::change_spill_state(Interval* interval, int spill_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
357 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
358 case oneDefinitionFound: {
a61af66fc99e Initial load
duke
parents:
diff changeset
359 int def_loop_depth = block_of_op_with_id(interval->spill_definition_pos())->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
360 int spill_loop_depth = block_of_op_with_id(spill_pos)->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
361
a61af66fc99e Initial load
duke
parents:
diff changeset
362 if (def_loop_depth < spill_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // the loop depth of the spilling position is higher then the loop depth
a61af66fc99e Initial load
duke
parents:
diff changeset
364 // at the definition of the interval -> move write to memory out of loop
a61af66fc99e Initial load
duke
parents:
diff changeset
365 // by storing at definitin of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
366 interval->set_spill_state(storeAtDefinition);
a61af66fc99e Initial load
duke
parents:
diff changeset
367 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 // the interval is currently spilled only once, so for now there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
369 // reason to store the interval at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
370 interval->set_spill_state(oneMoveInserted);
a61af66fc99e Initial load
duke
parents:
diff changeset
371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
372 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
374
a61af66fc99e Initial load
duke
parents:
diff changeset
375 case oneMoveInserted: {
a61af66fc99e Initial load
duke
parents:
diff changeset
376 // the interval is spilled more then once, so it is better to store it to
a61af66fc99e Initial load
duke
parents:
diff changeset
377 // memory at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
378 interval->set_spill_state(storeAtDefinition);
a61af66fc99e Initial load
duke
parents:
diff changeset
379 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
381
a61af66fc99e Initial load
duke
parents:
diff changeset
382 case storeAtDefinition:
a61af66fc99e Initial load
duke
parents:
diff changeset
383 case startInMemory:
a61af66fc99e Initial load
duke
parents:
diff changeset
384 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
385 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
386 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
387 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
388
a61af66fc99e Initial load
duke
parents:
diff changeset
389 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
390 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
393
a61af66fc99e Initial load
duke
parents:
diff changeset
394
a61af66fc99e Initial load
duke
parents:
diff changeset
395 bool LinearScan::must_store_at_definition(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
396 return i->is_split_parent() && i->spill_state() == storeAtDefinition;
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // called once before asignment of register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
400 void LinearScan::eliminate_spill_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
401 TIME_LINEAR_SCAN(timer_eliminate_spill_moves);
a61af66fc99e Initial load
duke
parents:
diff changeset
402 TRACE_LINEAR_SCAN(3, tty->print_cr("***** Eliminating unnecessary spill moves"));
a61af66fc99e Initial load
duke
parents:
diff changeset
403
a61af66fc99e Initial load
duke
parents:
diff changeset
404 // collect all intervals that must be stored after their definion.
a61af66fc99e Initial load
duke
parents:
diff changeset
405 // the list is sorted by Interval::spill_definition_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
406 Interval* interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
407 Interval* temp_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
408 create_unhandled_lists(&interval, &temp_list, must_store_at_definition, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
409
a61af66fc99e Initial load
duke
parents:
diff changeset
410 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
411 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
412 Interval* temp = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
413 while (temp != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
414 assert(temp->spill_definition_pos() > 0, "invalid spill definition pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
415 if (prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 assert(temp->from() >= prev->from(), "intervals not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
417 assert(temp->spill_definition_pos() >= prev->spill_definition_pos(), "when intervals are sorted by from, then they must also be sorted by spill_definition_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
418 }
a61af66fc99e Initial load
duke
parents:
diff changeset
419
a61af66fc99e Initial load
duke
parents:
diff changeset
420 assert(temp->canonical_spill_slot() >= LinearScan::nof_regs, "interval has no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
421 assert(temp->spill_definition_pos() >= temp->from(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
422 assert(temp->spill_definition_pos() <= temp->from() + 2, "only intervals defined once at their start-pos can be optimized");
a61af66fc99e Initial load
duke
parents:
diff changeset
423
a61af66fc99e Initial load
duke
parents:
diff changeset
424 TRACE_LINEAR_SCAN(4, tty->print_cr("interval %d (from %d to %d) must be stored at %d", temp->reg_num(), temp->from(), temp->to(), temp->spill_definition_pos()));
a61af66fc99e Initial load
duke
parents:
diff changeset
425
a61af66fc99e Initial load
duke
parents:
diff changeset
426 temp = temp->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
428 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
429
a61af66fc99e Initial load
duke
parents:
diff changeset
430 LIR_InsertionBuffer insertion_buffer;
a61af66fc99e Initial load
duke
parents:
diff changeset
431 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
432 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
433 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
434 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
435 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
436 bool has_new = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
439 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
440 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
441 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
442
a61af66fc99e Initial load
duke
parents:
diff changeset
443 if (op_id == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // remove move from register to stack if the stack slot is guaranteed to be correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // only moves that have been inserted by LinearScan can be removed.
a61af66fc99e Initial load
duke
parents:
diff changeset
446 assert(op->code() == lir_move, "only moves can have a op_id of -1");
a61af66fc99e Initial load
duke
parents:
diff changeset
447 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
448 assert(op->as_Op1()->result_opr()->is_virtual(), "LinearScan inserts only moves to virtual registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
449
a61af66fc99e Initial load
duke
parents:
diff changeset
450 LIR_Op1* op1 = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
451 Interval* interval = interval_at(op1->result_opr()->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
452
a61af66fc99e Initial load
duke
parents:
diff changeset
453 if (interval->assigned_reg() >= LinearScan::nof_regs && interval->always_in_memory()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // move target is a stack slot that is always correct, so eliminate instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
455 TRACE_LINEAR_SCAN(4, tty->print_cr("eliminating move from interval %d to %d", op1->in_opr()->vreg_number(), op1->result_opr()->vreg_number()));
a61af66fc99e Initial load
duke
parents:
diff changeset
456 instructions->at_put(j, NULL); // NULL-instructions are deleted by assign_reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
458
a61af66fc99e Initial load
duke
parents:
diff changeset
459 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
460 // insert move from register to stack just after the beginning of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
461 assert(interval == Interval::end() || interval->spill_definition_pos() >= op_id, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
462 assert(interval == Interval::end() || (interval->is_split_parent() && interval->spill_state() == storeAtDefinition), "invalid interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
463
a61af66fc99e Initial load
duke
parents:
diff changeset
464 while (interval != Interval::end() && interval->spill_definition_pos() == op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
465 if (!has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
466 // prepare insertion buffer (appended when all instructions of the block are processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
467 insertion_buffer.init(block->lir());
a61af66fc99e Initial load
duke
parents:
diff changeset
468 has_new = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
470
a61af66fc99e Initial load
duke
parents:
diff changeset
471 LIR_Opr from_opr = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
472 LIR_Opr to_opr = canonical_spill_opr(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
473 assert(from_opr->is_fixed_cpu() || from_opr->is_fixed_fpu(), "from operand must be a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
474 assert(to_opr->is_stack(), "to operand must be a stack slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
475
a61af66fc99e Initial load
duke
parents:
diff changeset
476 insertion_buffer.move(j, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
477 TRACE_LINEAR_SCAN(4, tty->print_cr("inserting move after definition of interval %d to stack slot %d at op_id %d", interval->reg_num(), interval->canonical_spill_slot() - LinearScan::nof_regs, op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
478
a61af66fc99e Initial load
duke
parents:
diff changeset
479 interval = interval->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
482 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
483
a61af66fc99e Initial load
duke
parents:
diff changeset
484 if (has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 block->lir()->append(&insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
487 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
488
a61af66fc99e Initial load
duke
parents:
diff changeset
489 assert(interval == Interval::end(), "missed an interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
491
a61af66fc99e Initial load
duke
parents:
diff changeset
492
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // ********** Phase 1: number all instructions in all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
494 // Compute depth-first and linear scan block orders, and number LIR_Op nodes for linear scan.
a61af66fc99e Initial load
duke
parents:
diff changeset
495
a61af66fc99e Initial load
duke
parents:
diff changeset
496 void LinearScan::number_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
497 {
a61af66fc99e Initial load
duke
parents:
diff changeset
498 // dummy-timer to measure the cost of the timer itself
a61af66fc99e Initial load
duke
parents:
diff changeset
499 // (this time is then subtracted from all other timers to get the real value)
a61af66fc99e Initial load
duke
parents:
diff changeset
500 TIME_LINEAR_SCAN(timer_do_nothing);
a61af66fc99e Initial load
duke
parents:
diff changeset
501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
502 TIME_LINEAR_SCAN(timer_number_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
503
a61af66fc99e Initial load
duke
parents:
diff changeset
504 // Assign IDs to LIR nodes and build a mapping, lir_ops, from ID to LIR_Op node.
a61af66fc99e Initial load
duke
parents:
diff changeset
505 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
506 int num_instructions = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
507 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
508 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
509 num_instructions += block_at(i)->lir()->instructions_list()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // initialize with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
513 _lir_ops = LIR_OpArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
514 _block_of_op = BlockBeginArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
515
a61af66fc99e Initial load
duke
parents:
diff changeset
516 int op_id = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
517 int idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
518
a61af66fc99e Initial load
duke
parents:
diff changeset
519 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
520 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
521 block->set_first_lir_instruction_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
522 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
523
a61af66fc99e Initial load
duke
parents:
diff changeset
524 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
525 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
526 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
527 op->set_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529 _lir_ops.at_put(idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
530 _block_of_op.at_put(idx, block);
a61af66fc99e Initial load
duke
parents:
diff changeset
531 assert(lir_op_with_id(op_id) == op, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
532
a61af66fc99e Initial load
duke
parents:
diff changeset
533 idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
534 op_id += 2; // numbering of lir_ops by two
a61af66fc99e Initial load
duke
parents:
diff changeset
535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
536 block->set_last_lir_instruction_id(op_id - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
537 }
a61af66fc99e Initial load
duke
parents:
diff changeset
538 assert(idx == num_instructions, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
539 assert(idx * 2 == op_id, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
540
a61af66fc99e Initial load
duke
parents:
diff changeset
541 _has_call = BitMap(num_instructions); _has_call.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
542 _has_info = BitMap(num_instructions); _has_info.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
543 }
a61af66fc99e Initial load
duke
parents:
diff changeset
544
a61af66fc99e Initial load
duke
parents:
diff changeset
545
a61af66fc99e Initial load
duke
parents:
diff changeset
546 // ********** Phase 2: compute local live sets separately for each block
a61af66fc99e Initial load
duke
parents:
diff changeset
547 // (sets live_gen and live_kill for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
548
a61af66fc99e Initial load
duke
parents:
diff changeset
549 void LinearScan::set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill) {
a61af66fc99e Initial load
duke
parents:
diff changeset
550 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
551 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
552
a61af66fc99e Initial load
duke
parents:
diff changeset
553 // check some asumptions about debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
554 assert(!value->type()->is_illegal(), "if this local is used by the interpreter it shouldn't be of indeterminate type");
a61af66fc99e Initial load
duke
parents:
diff changeset
555 assert(con == NULL || opr->is_virtual() || opr->is_constant() || opr->is_illegal(), "asumption: Constant instructions have only constant operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
556 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
557
a61af66fc99e Initial load
duke
parents:
diff changeset
558 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
559 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
560 int reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
561 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
562 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
563 TRACE_LINEAR_SCAN(4, tty->print_cr(" Setting live_gen for value %c%d, LIR op_id %d, register number %d", value->type()->tchar(), value->id(), op->id(), reg));
a61af66fc99e Initial load
duke
parents:
diff changeset
564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
567
a61af66fc99e Initial load
duke
parents:
diff changeset
568
a61af66fc99e Initial load
duke
parents:
diff changeset
569 void LinearScan::compute_local_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
570 TIME_LINEAR_SCAN(timer_compute_local_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
571
a61af66fc99e Initial load
duke
parents:
diff changeset
572 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
573 int live_size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
574 bool local_has_fpu_registers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
575 int local_num_calls = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
576 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
577
a61af66fc99e Initial load
duke
parents:
diff changeset
578 BitMap2D local_interval_in_loop = BitMap2D(_num_virtual_regs, num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
579 local_interval_in_loop.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
580
a61af66fc99e Initial load
duke
parents:
diff changeset
581 // iterate all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
582 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
583 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
584
a61af66fc99e Initial load
duke
parents:
diff changeset
585 BitMap live_gen(live_size); live_gen.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
586 BitMap live_kill(live_size); live_kill.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
587
a61af66fc99e Initial load
duke
parents:
diff changeset
588 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
589 // Phi functions at the begin of an exception handler are
a61af66fc99e Initial load
duke
parents:
diff changeset
590 // implicitly defined (= killed) at the beginning of the block.
a61af66fc99e Initial load
duke
parents:
diff changeset
591 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
592 live_kill.set_bit(phi->operand()->vreg_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
593 );
a61af66fc99e Initial load
duke
parents:
diff changeset
594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
595
a61af66fc99e Initial load
duke
parents:
diff changeset
596 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
597 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
598
a61af66fc99e Initial load
duke
parents:
diff changeset
599 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
600 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
601 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
602 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
603
a61af66fc99e Initial load
duke
parents:
diff changeset
604 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
605 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
606
a61af66fc99e Initial load
duke
parents:
diff changeset
607 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 _has_call.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
609 local_num_calls++;
a61af66fc99e Initial load
duke
parents:
diff changeset
610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
611 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
612 _has_info.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
613 }
a61af66fc99e Initial load
duke
parents:
diff changeset
614
a61af66fc99e Initial load
duke
parents:
diff changeset
615 // iterate input operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
616 int k, n, reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
617 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
618 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
619 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
620 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
621
a61af66fc99e Initial load
duke
parents:
diff changeset
622 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
623 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
624 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
625 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
626 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
627 TRACE_LINEAR_SCAN(4, tty->print_cr(" Setting live_gen for register %d at instruction %d", reg, op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
629 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
630 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
632 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
634
a61af66fc99e Initial load
duke
parents:
diff changeset
635 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
636 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
637 // they need not be processed in live sets.
a61af66fc99e Initial load
duke
parents:
diff changeset
638 // this is checked by these assertions to be sure about it.
a61af66fc99e Initial load
duke
parents:
diff changeset
639 // the entry block may have incoming values in registers, which is ok.
a61af66fc99e Initial load
duke
parents:
diff changeset
640 if (!opr->is_virtual_register() && block != ir()->start()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
641 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
642 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
643 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
645 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
646 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
647 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
650 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
652
a61af66fc99e Initial load
duke
parents:
diff changeset
653 // Add uses of live locals from interpreter's point of view for proper debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
654 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
655 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
656 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
657 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
658 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
659 set_live_gen_kill(value, op, live_gen, live_kill)
a61af66fc99e Initial load
duke
parents:
diff changeset
660 );
a61af66fc99e Initial load
duke
parents:
diff changeset
661 }
a61af66fc99e Initial load
duke
parents:
diff changeset
662
a61af66fc99e Initial load
duke
parents:
diff changeset
663 // iterate temp operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
664 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
665 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
667 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
668
a61af66fc99e Initial load
duke
parents:
diff changeset
669 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
670 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
671 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
672 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
673 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
674 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
676 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
677 }
a61af66fc99e Initial load
duke
parents:
diff changeset
678
a61af66fc99e Initial load
duke
parents:
diff changeset
679 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
680 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
681 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
682 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
683 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
684 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
685 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
686 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
687 }
a61af66fc99e Initial load
duke
parents:
diff changeset
688 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
689 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
690 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
691 }
a61af66fc99e Initial load
duke
parents:
diff changeset
692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
693 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
694 }
a61af66fc99e Initial load
duke
parents:
diff changeset
695
a61af66fc99e Initial load
duke
parents:
diff changeset
696 // iterate output operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
697 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
698 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
699 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
700 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
701
a61af66fc99e Initial load
duke
parents:
diff changeset
702 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
703 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
704 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
705 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
706 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
707 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
709 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
710 }
a61af66fc99e Initial load
duke
parents:
diff changeset
711
a61af66fc99e Initial load
duke
parents:
diff changeset
712 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
713 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
714 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
715 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
716 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
717 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
718 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
719 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
720 }
a61af66fc99e Initial load
duke
parents:
diff changeset
721 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
722 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
723 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
724 }
a61af66fc99e Initial load
duke
parents:
diff changeset
725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
726 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
728 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
729
a61af66fc99e Initial load
duke
parents:
diff changeset
730 block->set_live_gen (live_gen);
a61af66fc99e Initial load
duke
parents:
diff changeset
731 block->set_live_kill(live_kill);
a61af66fc99e Initial load
duke
parents:
diff changeset
732 block->set_live_in (BitMap(live_size)); block->live_in().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
733 block->set_live_out (BitMap(live_size)); block->live_out().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
734
a61af66fc99e Initial load
duke
parents:
diff changeset
735 TRACE_LINEAR_SCAN(4, tty->print("live_gen B%d ", block->block_id()); print_bitmap(block->live_gen()));
a61af66fc99e Initial load
duke
parents:
diff changeset
736 TRACE_LINEAR_SCAN(4, tty->print("live_kill B%d ", block->block_id()); print_bitmap(block->live_kill()));
a61af66fc99e Initial load
duke
parents:
diff changeset
737 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
738
a61af66fc99e Initial load
duke
parents:
diff changeset
739 // propagate local calculated information into LinearScan object
a61af66fc99e Initial load
duke
parents:
diff changeset
740 _has_fpu_registers = local_has_fpu_registers;
a61af66fc99e Initial load
duke
parents:
diff changeset
741 compilation()->set_has_fpu_code(local_has_fpu_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
742
a61af66fc99e Initial load
duke
parents:
diff changeset
743 _num_calls = local_num_calls;
a61af66fc99e Initial load
duke
parents:
diff changeset
744 _interval_in_loop = local_interval_in_loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
745 }
a61af66fc99e Initial load
duke
parents:
diff changeset
746
a61af66fc99e Initial load
duke
parents:
diff changeset
747
a61af66fc99e Initial load
duke
parents:
diff changeset
748 // ********** Phase 3: perform a backward dataflow analysis to compute global live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
749 // (sets live_in and live_out for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
750
a61af66fc99e Initial load
duke
parents:
diff changeset
751 void LinearScan::compute_global_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
752 TIME_LINEAR_SCAN(timer_compute_global_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
753
a61af66fc99e Initial load
duke
parents:
diff changeset
754 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
755 bool change_occurred;
a61af66fc99e Initial load
duke
parents:
diff changeset
756 bool change_occurred_in_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
757 int iteration_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
758 BitMap live_out(live_set_size()); live_out.clear(); // scratch set for calculations
a61af66fc99e Initial load
duke
parents:
diff changeset
759
a61af66fc99e Initial load
duke
parents:
diff changeset
760 // Perform a backward dataflow analysis to compute live_out and live_in for each block.
a61af66fc99e Initial load
duke
parents:
diff changeset
761 // The loop is executed until a fixpoint is reached (no changes in an iteration)
a61af66fc99e Initial load
duke
parents:
diff changeset
762 // Exception handlers must be processed because not all live values are
a61af66fc99e Initial load
duke
parents:
diff changeset
763 // present in the state array, e.g. because of global value numbering
a61af66fc99e Initial load
duke
parents:
diff changeset
764 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
765 change_occurred = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
766
a61af66fc99e Initial load
duke
parents:
diff changeset
767 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
768 for (int i = num_blocks - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
769 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
770
a61af66fc99e Initial load
duke
parents:
diff changeset
771 change_occurred_in_block = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
772
a61af66fc99e Initial load
duke
parents:
diff changeset
773 // live_out(block) is the union of live_in(sux), for successors sux of block
a61af66fc99e Initial load
duke
parents:
diff changeset
774 int n = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
775 int e = block->number_of_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
776 if (n + e > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
777 // block has successors
a61af66fc99e Initial load
duke
parents:
diff changeset
778 if (n > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
779 live_out.set_from(block->sux_at(0)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
780 for (int j = 1; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
781 live_out.set_union(block->sux_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
783 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
784 live_out.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
785 }
a61af66fc99e Initial load
duke
parents:
diff changeset
786 for (int j = 0; j < e; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
787 live_out.set_union(block->exception_handler_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
788 }
a61af66fc99e Initial load
duke
parents:
diff changeset
789
a61af66fc99e Initial load
duke
parents:
diff changeset
790 if (!block->live_out().is_same(live_out)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
791 // A change occurred. Swap the old and new live out sets to avoid copying.
a61af66fc99e Initial load
duke
parents:
diff changeset
792 BitMap temp = block->live_out();
a61af66fc99e Initial load
duke
parents:
diff changeset
793 block->set_live_out(live_out);
a61af66fc99e Initial load
duke
parents:
diff changeset
794 live_out = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
795
a61af66fc99e Initial load
duke
parents:
diff changeset
796 change_occurred = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
797 change_occurred_in_block = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
799 }
a61af66fc99e Initial load
duke
parents:
diff changeset
800
a61af66fc99e Initial load
duke
parents:
diff changeset
801 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
802 // live_in(block) is the union of live_gen(block) with (live_out(block) & !live_kill(block))
a61af66fc99e Initial load
duke
parents:
diff changeset
803 // note: live_in has to be computed only in first iteration or if live_out has changed!
a61af66fc99e Initial load
duke
parents:
diff changeset
804 BitMap live_in = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
805 live_in.set_from(block->live_out());
a61af66fc99e Initial load
duke
parents:
diff changeset
806 live_in.set_difference(block->live_kill());
a61af66fc99e Initial load
duke
parents:
diff changeset
807 live_in.set_union(block->live_gen());
a61af66fc99e Initial load
duke
parents:
diff changeset
808 }
a61af66fc99e Initial load
duke
parents:
diff changeset
809
a61af66fc99e Initial load
duke
parents:
diff changeset
810 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
811 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
812 char c = ' ';
a61af66fc99e Initial load
duke
parents:
diff changeset
813 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
814 c = '*';
a61af66fc99e Initial load
duke
parents:
diff changeset
815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
816 tty->print("(%d) live_in%c B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
817 tty->print("(%d) live_out%c B%d ", iteration_count, c, block->block_id()); print_bitmap(block->live_out());
a61af66fc99e Initial load
duke
parents:
diff changeset
818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
819 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
821 iteration_count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
822
a61af66fc99e Initial load
duke
parents:
diff changeset
823 if (change_occurred && iteration_count > 50) {
a61af66fc99e Initial load
duke
parents:
diff changeset
824 BAILOUT("too many iterations in compute_global_live_sets");
a61af66fc99e Initial load
duke
parents:
diff changeset
825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
826 } while (change_occurred);
a61af66fc99e Initial load
duke
parents:
diff changeset
827
a61af66fc99e Initial load
duke
parents:
diff changeset
828
a61af66fc99e Initial load
duke
parents:
diff changeset
829 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
830 // check that fixed intervals are not live at block boundaries
a61af66fc99e Initial load
duke
parents:
diff changeset
831 // (live set must be empty at fixed intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
832 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
833 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
834 for (int j = 0; j < LIR_OprDesc::vreg_base; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
835 assert(block->live_in().at(j) == false, "live_in set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
836 assert(block->live_out().at(j) == false, "live_out set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
837 assert(block->live_gen().at(j) == false, "live_gen set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
838 }
a61af66fc99e Initial load
duke
parents:
diff changeset
839 }
a61af66fc99e Initial load
duke
parents:
diff changeset
840 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
841
a61af66fc99e Initial load
duke
parents:
diff changeset
842 // check that the live_in set of the first block is empty
a61af66fc99e Initial load
duke
parents:
diff changeset
843 BitMap live_in_args(ir()->start()->live_in().size());
a61af66fc99e Initial load
duke
parents:
diff changeset
844 live_in_args.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
845 if (!ir()->start()->live_in().is_same(live_in_args)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
846 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
847 tty->print_cr("Error: live_in set of first block must be empty (when this fails, virtual registers are used before they are defined)");
a61af66fc99e Initial load
duke
parents:
diff changeset
848 tty->print_cr("affected registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
849 print_bitmap(ir()->start()->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
850
a61af66fc99e Initial load
duke
parents:
diff changeset
851 // print some additional information to simplify debugging
a61af66fc99e Initial load
duke
parents:
diff changeset
852 for (unsigned int i = 0; i < ir()->start()->live_in().size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
853 if (ir()->start()->live_in().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
854 Instruction* instr = gen()->instruction_for_vreg(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
855 tty->print_cr("* vreg %d (HIR instruction %c%d)", i, instr == NULL ? ' ' : instr->type()->tchar(), instr == NULL ? 0 : instr->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
856
a61af66fc99e Initial load
duke
parents:
diff changeset
857 for (int j = 0; j < num_blocks; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
858 BlockBegin* block = block_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
859 if (block->live_gen().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
860 tty->print_cr(" used in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
861 }
a61af66fc99e Initial load
duke
parents:
diff changeset
862 if (block->live_kill().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
863 tty->print_cr(" defined in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
864 }
a61af66fc99e Initial load
duke
parents:
diff changeset
865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
866 }
a61af66fc99e Initial load
duke
parents:
diff changeset
867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
868
a61af66fc99e Initial load
duke
parents:
diff changeset
869 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
870 // when this fails, virtual registers are used before they are defined.
a61af66fc99e Initial load
duke
parents:
diff changeset
871 assert(false, "live_in set of first block must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
872 // bailout of if this occurs in product mode.
a61af66fc99e Initial load
duke
parents:
diff changeset
873 bailout("live_in set of first block not empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
874 }
a61af66fc99e Initial load
duke
parents:
diff changeset
875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
876
a61af66fc99e Initial load
duke
parents:
diff changeset
877
a61af66fc99e Initial load
duke
parents:
diff changeset
878 // ********** Phase 4: build intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
879 // (fills the list _intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
880
a61af66fc99e Initial load
duke
parents:
diff changeset
881 void LinearScan::add_use(Value value, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
882 assert(!value->type()->is_illegal(), "if this value is used by the interpreter it shouldn't be of indeterminate type");
a61af66fc99e Initial load
duke
parents:
diff changeset
883 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
884 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
885
a61af66fc99e Initial load
duke
parents:
diff changeset
886 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
887 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
888 add_use(opr, from, to, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
890 }
a61af66fc99e Initial load
duke
parents:
diff changeset
891
a61af66fc99e Initial load
duke
parents:
diff changeset
892
a61af66fc99e Initial load
duke
parents:
diff changeset
893 void LinearScan::add_def(LIR_Opr opr, int def_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
894 TRACE_LINEAR_SCAN(2, tty->print(" def "); opr->print(tty); tty->print_cr(" def_pos %d (%d)", def_pos, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
895 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
896
a61af66fc99e Initial load
duke
parents:
diff changeset
897 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
898 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
899 add_def(opr->vreg_number(), def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
900
a61af66fc99e Initial load
duke
parents:
diff changeset
901 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
902 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
903 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
904 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
905 }
a61af66fc99e Initial load
duke
parents:
diff changeset
906 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
907 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
908 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
910 }
a61af66fc99e Initial load
duke
parents:
diff changeset
911 }
a61af66fc99e Initial load
duke
parents:
diff changeset
912
a61af66fc99e Initial load
duke
parents:
diff changeset
913 void LinearScan::add_use(LIR_Opr opr, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
914 TRACE_LINEAR_SCAN(2, tty->print(" use "); opr->print(tty); tty->print_cr(" from %d to %d (%d)", from, to, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
915 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
916
a61af66fc99e Initial load
duke
parents:
diff changeset
917 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
918 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
919 add_use(opr->vreg_number(), from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
920
a61af66fc99e Initial load
duke
parents:
diff changeset
921 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
922 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
923 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
924 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
925 }
a61af66fc99e Initial load
duke
parents:
diff changeset
926 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
927 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
928 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
929 }
a61af66fc99e Initial load
duke
parents:
diff changeset
930 }
a61af66fc99e Initial load
duke
parents:
diff changeset
931 }
a61af66fc99e Initial load
duke
parents:
diff changeset
932
a61af66fc99e Initial load
duke
parents:
diff changeset
933 void LinearScan::add_temp(LIR_Opr opr, int temp_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
934 TRACE_LINEAR_SCAN(2, tty->print(" temp "); opr->print(tty); tty->print_cr(" temp_pos %d (%d)", temp_pos, use_kind));
a61af66fc99e Initial load
duke
parents:
diff changeset
935 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
936
a61af66fc99e Initial load
duke
parents:
diff changeset
937 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
938 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
939 add_temp(opr->vreg_number(), temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
940
a61af66fc99e Initial load
duke
parents:
diff changeset
941 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
942 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
943 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
944 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
945 }
a61af66fc99e Initial load
duke
parents:
diff changeset
946 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
947 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
948 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
949 }
a61af66fc99e Initial load
duke
parents:
diff changeset
950 }
a61af66fc99e Initial load
duke
parents:
diff changeset
951 }
a61af66fc99e Initial load
duke
parents:
diff changeset
952
a61af66fc99e Initial load
duke
parents:
diff changeset
953
a61af66fc99e Initial load
duke
parents:
diff changeset
954 void LinearScan::add_def(int reg_num, int def_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
955 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
956 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
957 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
958
a61af66fc99e Initial load
duke
parents:
diff changeset
959 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
960 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
961 }
a61af66fc99e Initial load
duke
parents:
diff changeset
962
a61af66fc99e Initial load
duke
parents:
diff changeset
963 Range* r = interval->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
964 if (r->from() <= def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
965 // Update the starting point (when a range is first created for a use, its
a61af66fc99e Initial load
duke
parents:
diff changeset
966 // start is the beginning of the current block until a def is encountered.)
a61af66fc99e Initial load
duke
parents:
diff changeset
967 r->set_from(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
968 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
969
a61af66fc99e Initial load
duke
parents:
diff changeset
970 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
971 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
972 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
973 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
974 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
975 TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: def of reg %d at %d occurs without use", reg_num, def_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
976 }
a61af66fc99e Initial load
duke
parents:
diff changeset
977
a61af66fc99e Initial load
duke
parents:
diff changeset
978 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
979 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
980 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
981 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
982 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
983 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
984 }
a61af66fc99e Initial load
duke
parents:
diff changeset
985
a61af66fc99e Initial load
duke
parents:
diff changeset
986 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
987 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
988 TRACE_LINEAR_SCAN(2, tty->print_cr("Warning: dead value %d at %d in live intervals", reg_num, def_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
989 }
a61af66fc99e Initial load
duke
parents:
diff changeset
990
a61af66fc99e Initial load
duke
parents:
diff changeset
991 change_spill_definition_pos(interval, def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
992 if (use_kind == noUse && interval->spill_state() <= startInMemory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
993 // detection of method-parameters and roundfp-results
a61af66fc99e Initial load
duke
parents:
diff changeset
994 // TODO: move this directly to position where use-kind is computed
a61af66fc99e Initial load
duke
parents:
diff changeset
995 interval->set_spill_state(startInMemory);
a61af66fc99e Initial load
duke
parents:
diff changeset
996 }
a61af66fc99e Initial load
duke
parents:
diff changeset
997 }
a61af66fc99e Initial load
duke
parents:
diff changeset
998
a61af66fc99e Initial load
duke
parents:
diff changeset
999 void LinearScan::add_use(int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1005
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1009
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 interval->add_range(from, to);
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 interval->add_use_pos(to, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1013
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 void LinearScan::add_temp(int reg_num, int temp_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1020
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1024
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 interval->add_range(temp_pos, temp_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 interval->add_use_pos(temp_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1028
a61af66fc99e Initial load
duke
parents:
diff changeset
1029
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 // the results of this functions are used for optimizing spilling and reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 // if the functions return shouldHaveRegister and the interval is spilled,
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 // it is not reloaded to a register.
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 IntervalUseKind LinearScan::use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1034 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
a61af66fc99e Initial load
duke
parents:
diff changeset
1039
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 // Begin of an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 // This interval will always get a stack slot first, so return noUse.
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1044
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 } else if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 // method argument (condition must be equal to handle_method_arguments)
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1048
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 // input operand must have a register instead of output operand (leads to better register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1058
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 if (opr->is_virtual() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1060 gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 // result is a stack-slot, so prevent immediate reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1064
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1068
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 IntervalUseKind LinearScan::use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1071 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 bool result_in_memory = res->is_virtual() && gen()->is_vreg_flag_set(res->vreg_number(), LIRGenerator::must_start_in_memory);
a61af66fc99e Initial load
duke
parents:
diff changeset
1075
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 // Move to an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 // To avoid moves from stack to stack (not allowed) force the input operand to a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1080
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 // input operand must have a register instead of output operand (leads to better register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1088
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 // The input operand is not forced to a register (moves from stack to register are allowed),
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 // but it is faster if the input operand is in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1094
a61af66fc99e Initial load
duke
parents:
diff changeset
1095
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1096 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 if (op->code() == lir_cmove) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 // conditional moves can handle stack operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 assert(op->result_opr()->is_register(), "result must always be in a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1102
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 // optimizations for second input operand of arithmehtic operations on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 // this operand is allowed to be on the stack in some cases
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 BasicType opr_type = opr->type_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 if (opr_type == T_FLOAT || opr_type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 if ((UseSSE == 1 && opr_type == T_FLOAT) || UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 // SSE float instruction (T_DOUBLE only supported with SSE2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 // FPU stack float instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1134 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1135 assert((op2->result_opr()->is_register() || op->code() == lir_cmp) && op2->in_opr1()->is_register(), "cannot mark second operand as stack if others are not in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 }
13044
a905d33ce13a 8027751: C1 crashes in Weblogic with G1 enabled
iveresov
parents: 12969
diff changeset
1141 // We want to sometimes use logical operations on pointers, in particular in GC barriers.
a905d33ce13a 8027751: C1 crashes in Weblogic with G1 enabled
iveresov
parents: 12969
diff changeset
1142 // Since 64bit logical operations do not current support operands on stack, we have to make sure
a905d33ce13a 8027751: C1 crashes in Weblogic with G1 enabled
iveresov
parents: 12969
diff changeset
1143 // T_OBJECT doesn't get spilled along with T_LONG.
a905d33ce13a 8027751: C1 crashes in Weblogic with G1 enabled
iveresov
parents: 12969
diff changeset
1144 } else if (opr_type != T_LONG LP64_ONLY(&& opr_type != T_OBJECT)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 // integer instruction (note: long operands must always be in register)
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
1152 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 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
1158 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1163 #endif // X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1164
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1167 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1168
a61af66fc99e Initial load
duke
parents:
diff changeset
1169
a61af66fc99e Initial load
duke
parents:
diff changeset
1170 void LinearScan::handle_method_arguments(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 // special handling for method arguments (moves from stack to virtual register):
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 // the interval gets no register assigned, but the stack slot.
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 // it is split before the first use by the register allocator.
a61af66fc99e Initial load
duke
parents:
diff changeset
1174
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1176 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1178
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1181 int arg_size = compilation()->method()->arg_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 LIR_Opr o = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 if (o->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 assert(o->single_stack_ix() >= 0 && o->single_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 } else if (o->is_double_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 assert(o->double_stack_ix() >= 0 && o->double_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1188 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1190
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 assert(move->id() > 0, "invalid id");
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 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
1193 assert(move->result_opr()->is_virtual(), "result of move must be a virtual register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1194
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 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
1196 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1197
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 Interval* interval = interval_at(reg_num(move->result_opr()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1199
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 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
1201 interval->set_canonical_spill_slot(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 interval->assign_reg(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1206
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 void LinearScan::handle_doubleword_moves(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 // special handling for doubleword move from memory to register:
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 // in this case the registers of the input address and the result
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 // registers must not overlap -> add a temp range for the input registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1214
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 if (move->result_opr()->is_double_cpu() && move->in_opr()->is_pointer()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 LIR_Address* address = move->in_opr()->as_address_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 if (address != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 if (address->base()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 add_temp(address->base(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 if (address->index()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 add_temp(address->index(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1228
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 void LinearScan::add_register_hints(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 case lir_move: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 case lir_convert: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 assert(op->as_Op1() != NULL, "lir_move, lir_convert must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1235
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 LIR_Opr move_from = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 LIR_Opr move_to = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1238
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 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
1245 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 case lir_cmove: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 LIR_Op2* cmove = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1252
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 LIR_Opr move_from = cmove->in_opr1();
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 LIR_Opr move_to = cmove->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1255
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1259 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 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
1262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1268
a61af66fc99e Initial load
duke
parents:
diff changeset
1269
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 void LinearScan::build_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 TIME_LINEAR_SCAN(timer_build_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1272
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 // initialize interval list with expected number of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1274 // (32 is added to have some space for split children without having to resize the list)
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 _intervals = IntervalList(num_virtual_regs() + 32);
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 // initialize all slots that are used by build_intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1277 _intervals.at_put_grow(num_virtual_regs() - 1, NULL, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1278
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 // create a list with all caller-save registers (cpu, fpu, xmm)
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 // when an instruction is a call, a temp range is created for all these registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 int num_caller_save_registers = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1282 int caller_save_registers[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
1283
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 int i;
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
1285 for (i = 0; i < FrameMap::nof_caller_save_cpu_regs(); i++) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 LIR_Opr opr = FrameMap::caller_save_cpu_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1288 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1291
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 // temp ranges for fpu registers are only created when the method has
a61af66fc99e Initial load
duke
parents:
diff changeset
1293 // virtual fpu operands. Otherwise no allocation for fpu registers is
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 // perfomed and so the temp ranges would be useless
a61af66fc99e Initial load
duke
parents:
diff changeset
1295 if (has_fpu_registers()) {
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 if (UseSSE < 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 for (i = 0; i < FrameMap::nof_caller_save_fpu_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 LIR_Opr opr = FrameMap::caller_save_fpu_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 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1305 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 if (UseSSE > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 for (i = 0; i < FrameMap::nof_caller_save_xmm_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1309 LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1312 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1313 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1315 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 assert(num_caller_save_registers <= LinearScan::nof_regs, "out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1318
a61af66fc99e Initial load
duke
parents:
diff changeset
1319
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1321
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 for (i = block_count() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1324 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1325 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1326 int block_from = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 int block_to = block->last_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1328
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 assert(block_from == instructions->at(0)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 assert(block_to == instructions->at(instructions->length() - 1)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1331
a61af66fc99e Initial load
duke
parents:
diff changeset
1332 // Update intervals for registers live at the end of this block;
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 BitMap live = block->live_out();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1334 int size = (int)live.size();
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1335 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
1336 assert(live.at(number), "should not stop here otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1337 assert(number >= LIR_OprDesc::vreg_base, "fixed intervals must not be live on block bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 TRACE_LINEAR_SCAN(2, tty->print_cr("live in %d to %d", number, block_to + 2));
a61af66fc99e Initial load
duke
parents:
diff changeset
1339
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 add_use(number, block_from, block_to + 2, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1341
a61af66fc99e Initial load
duke
parents:
diff changeset
1342 // add special use positions for loop-end blocks when the
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 // interval is used anywhere inside this loop. It's possible
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 // that the block was part of a non-natural loop, so it might
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 // have an invalid loop index.
a61af66fc99e Initial load
duke
parents:
diff changeset
1346 if (block->is_set(BlockBegin::linear_scan_loop_end_flag) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 block->loop_index() != -1 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 is_interval_in_loop(number, block->loop_index())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 interval_at(number)->add_use_pos(block_to + 1, loopEndMarker);
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1352
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 // iterate all instructions of the block in reverse order.
a61af66fc99e Initial load
duke
parents:
diff changeset
1354 // skip the first instruction because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1355 // definitions of intervals are processed before uses
a61af66fc99e Initial load
duke
parents:
diff changeset
1356 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1357 for (int j = instructions->length() - 1; j >= 1; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1358 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1360
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1362 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1363
a61af66fc99e Initial load
duke
parents:
diff changeset
1364 // add a temp range for each register if operation destroys caller-save registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1365 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 for (int k = 0; k < num_caller_save_registers; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 add_temp(caller_save_registers[k], op_id, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1369 TRACE_LINEAR_SCAN(4, tty->print_cr("operation destroys all caller-save registers"));
a61af66fc99e Initial load
duke
parents:
diff changeset
1370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1371
a61af66fc99e Initial load
duke
parents:
diff changeset
1372 // Add any platform dependent temps
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 pd_add_temps(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1374
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 // visit definitions (output and temp operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1376 int k, n;
a61af66fc99e Initial load
duke
parents:
diff changeset
1377 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1378 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1379 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1380 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1381 add_def(opr, op_id, use_kind_of_output_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1383
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1385 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1388 add_temp(opr, op_id, mustHaveRegister);
a61af66fc99e Initial load
duke
parents:
diff changeset
1389 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1390
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 // visit uses (input operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1393 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1394 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1396 add_use(opr, block_from, op_id, use_kind_of_input_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1398
a61af66fc99e Initial load
duke
parents:
diff changeset
1399 // Add uses of live locals from interpreter's point of view for proper
a61af66fc99e Initial load
duke
parents:
diff changeset
1400 // debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1401 // Treat these operands as temp values (if the life range is extended
a61af66fc99e Initial load
duke
parents:
diff changeset
1402 // to a call site, the value would be in a register at the call otherwise)
a61af66fc99e Initial load
duke
parents:
diff changeset
1403 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1404 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1405 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
1407 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 add_use(value, block_from, op_id + 1, noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1409 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1410 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1411
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 // special steps for some instructions (especially moves)
a61af66fc99e Initial load
duke
parents:
diff changeset
1413 handle_method_arguments(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1414 handle_doubleword_moves(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1415 add_register_hints(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1416
a61af66fc99e Initial load
duke
parents:
diff changeset
1417 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1418 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1419
a61af66fc99e Initial load
duke
parents:
diff changeset
1420
a61af66fc99e Initial load
duke
parents:
diff changeset
1421 // add the range [0, 1[ to all fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1422 // -> the register allocator need not handle unhandled fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1423 for (int n = 0; n < LinearScan::nof_regs; n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1424 Interval* interval = interval_at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1426 interval->add_range(0, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1430
a61af66fc99e Initial load
duke
parents:
diff changeset
1431
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 // ********** Phase 5: actual register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
1433
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 int LinearScan::interval_cmp(Interval** a, Interval** b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 if (*a != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 return (*a)->from() - (*b)->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1438 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1442 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1449
a61af66fc99e Initial load
duke
parents:
diff changeset
1450 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1451 bool LinearScan::is_sorted(IntervalArray* intervals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1452 int from = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1453 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1454 for (i = 0; i < intervals->length(); i ++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1455 Interval* it = intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1456 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 if (from > it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 assert(false, "");
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1461 from = it->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1462 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1464
a61af66fc99e Initial load
duke
parents:
diff changeset
1465 // check in both directions if sorted list and unsorted list contain same intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 if (interval_at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1476 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1477 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1480 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1481 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1484 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1486
a61af66fc99e Initial load
duke
parents:
diff changeset
1487 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1490
a61af66fc99e Initial load
duke
parents:
diff changeset
1491 void LinearScan::add_to_list(Interval** first, Interval** prev, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 if (*prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1493 (*prev)->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1494 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1495 *first = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1497 *prev = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1499
a61af66fc99e Initial load
duke
parents:
diff changeset
1500 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
1501 assert(is_sorted(_sorted_intervals), "interval list is not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
1502
a61af66fc99e Initial load
duke
parents:
diff changeset
1503 *list1 = *list2 = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
1504
a61af66fc99e Initial load
duke
parents:
diff changeset
1505 Interval* list1_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1506 Interval* list2_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 Interval* v;
a61af66fc99e Initial load
duke
parents:
diff changeset
1508
a61af66fc99e Initial load
duke
parents:
diff changeset
1509 const int n = _sorted_intervals->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1510 for (int i = 0; i < n; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1511 v = _sorted_intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1512 if (v == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
1513
a61af66fc99e Initial load
duke
parents:
diff changeset
1514 if (is_list1(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 add_to_list(list1, &list1_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 } else if (is_list2 == NULL || is_list2(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 add_to_list(list2, &list2_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1518 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1520
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 if (list1_prev != NULL) list1_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 if (list2_prev != NULL) list2_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1523
a61af66fc99e Initial load
duke
parents:
diff changeset
1524 assert(list1_prev == NULL || list1_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1525 assert(list2_prev == NULL || list2_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1526 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1527
a61af66fc99e Initial load
duke
parents:
diff changeset
1528
a61af66fc99e Initial load
duke
parents:
diff changeset
1529 void LinearScan::sort_intervals_before_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1530 TIME_LINEAR_SCAN(timer_sort_intervals_before);
a61af66fc99e Initial load
duke
parents:
diff changeset
1531
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1532 if (_needs_full_resort) {
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1533 // There is no known reason why this should occur but just in case...
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1534 assert(false, "should never occur");
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1535 // Re-sort existing interval list because an Interval::from() has changed
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1536 _sorted_intervals->sort(interval_cmp);
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1537 _needs_full_resort = false;
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1538 }
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1539
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 IntervalList* unsorted_list = &_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 int unsorted_len = unsorted_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1542 int sorted_len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 int unsorted_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
1544 int sorted_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1545 int sorted_from_max = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1546
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 // calc number of items for sorted list (sorted list must not contain NULL values)
a61af66fc99e Initial load
duke
parents:
diff changeset
1548 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1549 if (unsorted_list->at(unsorted_idx) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 sorted_len++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1551 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 IntervalArray* sorted_list = new IntervalArray(sorted_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1554
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 // special sorting algorithm: the original interval-list is almost sorted,
a61af66fc99e Initial load
duke
parents:
diff changeset
1556 // only some intervals are swapped. So this is much faster than a complete QuickSort
a61af66fc99e Initial load
duke
parents:
diff changeset
1557 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1558 Interval* cur_interval = unsorted_list->at(unsorted_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
1559
a61af66fc99e Initial load
duke
parents:
diff changeset
1560 if (cur_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 int cur_from = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1562
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 if (sorted_from_max <= cur_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 sorted_list->at_put(sorted_idx++, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 sorted_from_max = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1566 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1567 // the asumption that the intervals are already sorted failed,
a61af66fc99e Initial load
duke
parents:
diff changeset
1568 // so this interval must be sorted in manually
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1570 for (j = sorted_idx - 1; j >= 0 && cur_from < sorted_list->at(j)->from(); j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1571 sorted_list->at_put(j + 1, sorted_list->at(j));
a61af66fc99e Initial load
duke
parents:
diff changeset
1572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1573 sorted_list->at_put(j + 1, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 sorted_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1576 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1578 _sorted_intervals = sorted_list;
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1579 assert(is_sorted(_sorted_intervals), "intervals unsorted");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1581
a61af66fc99e Initial load
duke
parents:
diff changeset
1582 void LinearScan::sort_intervals_after_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1583 TIME_LINEAR_SCAN(timer_sort_intervals_after);
a61af66fc99e Initial load
duke
parents:
diff changeset
1584
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1585 if (_needs_full_resort) {
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1586 // Re-sort existing interval list because an Interval::from() has changed
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1587 _sorted_intervals->sort(interval_cmp);
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1588 _needs_full_resort = false;
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1589 }
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1590
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1591 IntervalArray* old_list = _sorted_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1592 IntervalList* new_list = _new_intervals_from_allocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
1593 int old_len = old_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1594 int new_len = new_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1595
a61af66fc99e Initial load
duke
parents:
diff changeset
1596 if (new_len == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1597 // no intervals have been added during allocation, so sorted list is already up to date
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1598 assert(is_sorted(_sorted_intervals), "intervals unsorted");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1599 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1601
a61af66fc99e Initial load
duke
parents:
diff changeset
1602 // conventional sort-algorithm for new intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 new_list->sort(interval_cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1604
a61af66fc99e Initial load
duke
parents:
diff changeset
1605 // merge old and new list (both already sorted) into one combined list
a61af66fc99e Initial load
duke
parents:
diff changeset
1606 IntervalArray* combined_list = new IntervalArray(old_len + new_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1607 int old_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 int new_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1609
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 while (old_idx + new_idx < old_len + new_len) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1611 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
1612 combined_list->at_put(old_idx + new_idx, old_list->at(old_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1613 old_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 combined_list->at_put(old_idx + new_idx, new_list->at(new_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1616 new_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1617 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1618 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1619
a61af66fc99e Initial load
duke
parents:
diff changeset
1620 _sorted_intervals = combined_list;
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1621 assert(is_sorted(_sorted_intervals), "intervals unsorted");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1623
a61af66fc99e Initial load
duke
parents:
diff changeset
1624
a61af66fc99e Initial load
duke
parents:
diff changeset
1625 void LinearScan::allocate_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 TIME_LINEAR_SCAN(timer_allocate_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
1627
a61af66fc99e Initial load
duke
parents:
diff changeset
1628 Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1630
a61af66fc99e Initial load
duke
parents:
diff changeset
1631 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
1632 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 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
1634 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1635 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1636 // fpu register allocation is omitted because no virtual fpu registers are present
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 // just check this again...
a61af66fc99e Initial load
duke
parents:
diff changeset
1638 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
1639 assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1642
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 // allocate cpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1645 cpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 cpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1647
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 // allocate fpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 fpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 fpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1653 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1655
a61af66fc99e Initial load
duke
parents:
diff changeset
1656
a61af66fc99e Initial load
duke
parents:
diff changeset
1657 // ********** Phase 6: resolve data flow
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 // (insert moves at edges between blocks if intervals have been split)
a61af66fc99e Initial load
duke
parents:
diff changeset
1659
a61af66fc99e Initial load
duke
parents:
diff changeset
1660 // wrapper for Interval::split_child_at_op_id that performs a bailout in product mode
a61af66fc99e Initial load
duke
parents:
diff changeset
1661 // instead of returning NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 Interval* LinearScan::split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1663 Interval* result = interval->split_child_at_op_id(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1664 if (result != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
1666 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1667
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 assert(false, "must find an interval, but do a clean bailout in product mode");
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 result = new Interval(LIR_OprDesc::vreg_base);
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 result->assign_reg(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1671 result->set_type(T_INT);
a61af66fc99e Initial load
duke
parents:
diff changeset
1672 BAILOUT_("LinearScan: interval is NULL", result);
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1674
a61af66fc99e Initial load
duke
parents:
diff changeset
1675
a61af66fc99e Initial load
duke
parents:
diff changeset
1676 Interval* LinearScan::interval_at_block_begin(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1677 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1678 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1679
a61af66fc99e Initial load
duke
parents:
diff changeset
1680 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
1681 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1682
a61af66fc99e Initial load
duke
parents:
diff changeset
1683 Interval* LinearScan::interval_at_block_end(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1686
a61af66fc99e Initial load
duke
parents:
diff changeset
1687 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
1688 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1689
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 Interval* LinearScan::interval_at_op_id(int reg_num, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1691 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1693
a61af66fc99e Initial load
duke
parents:
diff changeset
1694 return split_child_at_op_id(interval_at(reg_num), op_id, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1695 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1696
a61af66fc99e Initial load
duke
parents:
diff changeset
1697
a61af66fc99e Initial load
duke
parents:
diff changeset
1698 void LinearScan::resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1700
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 const int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 const int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1703 const BitMap live_at_edge = to_block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
1704
a61af66fc99e Initial load
duke
parents:
diff changeset
1705 // 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
1706 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
1707 assert(r < num_regs, "live information set for not exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1708 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
1709
a61af66fc99e Initial load
duke
parents:
diff changeset
1710 Interval* from_interval = interval_at_block_end(from_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1711 Interval* to_interval = interval_at_block_begin(to_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1712
a61af66fc99e Initial load
duke
parents:
diff changeset
1713 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
1714 // need to insert move instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1715 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1716 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1719
a61af66fc99e Initial load
duke
parents:
diff changeset
1720
a61af66fc99e Initial load
duke
parents:
diff changeset
1721 void LinearScan::resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1722 if (from_block->number_of_sux() <= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1723 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
1724
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 LIR_OpList* instructions = from_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1726 LIR_OpBranch* branch = instructions->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
1727 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1728 // insert moves before branch
a61af66fc99e Initial load
duke
parents:
diff changeset
1729 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
1730 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1731 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1732 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1733 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1734
a61af66fc99e Initial load
duke
parents:
diff changeset
1735 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1736 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
1737 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1738 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
1739
a61af66fc99e Initial load
duke
parents:
diff changeset
1740 // because the number of predecessor edges matches the number of
a61af66fc99e Initial load
duke
parents:
diff changeset
1741 // successor edges, blocks which are reached by switch statements
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 // may have be more than one predecessor but it will be guaranteed
a61af66fc99e Initial load
duke
parents:
diff changeset
1743 // that all predecessors will be the same.
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 for (int i = 0; i < to_block->number_of_preds(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1745 assert(from_block == to_block->pred_at(i), "all critical edges must be broken");
a61af66fc99e Initial load
duke
parents:
diff changeset
1746 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1747 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1748
a61af66fc99e Initial load
duke
parents:
diff changeset
1749 move_resolver.set_insert_position(to_block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1750 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1751 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1752
a61af66fc99e Initial load
duke
parents:
diff changeset
1753
a61af66fc99e Initial load
duke
parents:
diff changeset
1754 // insert necessary moves (spilling or reloading) at edges between blocks if interval has been split
a61af66fc99e Initial load
duke
parents:
diff changeset
1755 void LinearScan::resolve_data_flow() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1756 TIME_LINEAR_SCAN(timer_resolve_data_flow);
a61af66fc99e Initial load
duke
parents:
diff changeset
1757
a61af66fc99e Initial load
duke
parents:
diff changeset
1758 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1759 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1760 BitMap block_completed(num_blocks); block_completed.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1761 BitMap already_resolved(num_blocks); already_resolved.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1762
a61af66fc99e Initial load
duke
parents:
diff changeset
1763 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1764 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1765 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1766
a61af66fc99e Initial load
duke
parents:
diff changeset
1767 // check if block has only one predecessor and only one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
1768 if (block->number_of_preds() == 1 && block->number_of_sux() == 1 && block->number_of_exception_handlers() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1769 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1770 assert(instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1771 assert(instructions->last()->code() == lir_branch, "block with successors must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1772 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block with successor must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1773
a61af66fc99e Initial load
duke
parents:
diff changeset
1774 // check if block is empty (only label and branch)
a61af66fc99e Initial load
duke
parents:
diff changeset
1775 if (instructions->length() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1776 BlockBegin* pred = block->pred_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1777 BlockBegin* sux = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1778
a61af66fc99e Initial load
duke
parents:
diff changeset
1779 // prevent optimization of two consecutive blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1780 if (!block_completed.at(pred->linear_scan_number()) && !block_completed.at(sux->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1781 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
1782 block_completed.set_bit(block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1783
a61af66fc99e Initial load
duke
parents:
diff changeset
1784 // directly resolve between pred and sux (without looking at the empty block between)
a61af66fc99e Initial load
duke
parents:
diff changeset
1785 resolve_collect_mappings(pred, sux, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1786 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1787 move_resolver.set_insert_position(block->lir(), 0);
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 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1797 if (!block_completed.at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1798 BlockBegin* from_block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1799 already_resolved.set_from(block_completed);
a61af66fc99e Initial load
duke
parents:
diff changeset
1800
a61af66fc99e Initial load
duke
parents:
diff changeset
1801 int num_sux = from_block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
1802 for (int s = 0; s < num_sux; s++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1803 BlockBegin* to_block = from_block->sux_at(s);
a61af66fc99e Initial load
duke
parents:
diff changeset
1804
a61af66fc99e Initial load
duke
parents:
diff changeset
1805 // check for duplicate edges between the same blocks (can happen with switch blocks)
a61af66fc99e Initial load
duke
parents:
diff changeset
1806 if (!already_resolved.at(to_block->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1807 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
1808 already_resolved.set_bit(to_block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1809
a61af66fc99e Initial load
duke
parents:
diff changeset
1810 // collect all intervals that have been split between from_block and to_block
a61af66fc99e Initial load
duke
parents:
diff changeset
1811 resolve_collect_mappings(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1812 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1813 resolve_find_insert_pos(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1814 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1819 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1821
a61af66fc99e Initial load
duke
parents:
diff changeset
1822
a61af66fc99e Initial load
duke
parents:
diff changeset
1823 void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1824 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1825 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1826 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1828
a61af66fc99e Initial load
duke
parents:
diff changeset
1829 Interval* interval = interval_at_block_begin(block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1830 int reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1831 int regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
1832
a61af66fc99e Initial load
duke
parents:
diff changeset
1833 if ((reg < nof_regs && interval->always_in_memory()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1834 (use_fpu_stack_allocation() && reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1835 // the interval is split to get a short range that is located on the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1836 // in the following two cases:
a61af66fc99e Initial load
duke
parents:
diff changeset
1837 // * the interval started in memory (e.g. method parameter), but is currently in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1838 // this is an optimization for exception handling that reduces the number of moves that
a61af66fc99e Initial load
duke
parents:
diff changeset
1839 // are necessary for resolving the states when an exception uses this exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1840 // * the interval would be on the fpu stack at the begin of the exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1841 // this is not allowed because of the complicated fpu stack handling on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1842
a61af66fc99e Initial load
duke
parents:
diff changeset
1843 // range that will be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
1844 int from_op_id = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1845 int to_op_id = from_op_id + 1; // short live range of length 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1846 assert(interval->from() <= from_op_id && interval->to() >= to_op_id,
a61af66fc99e Initial load
duke
parents:
diff changeset
1847 "no split allowed between exception entry and first instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
1848
a61af66fc99e Initial load
duke
parents:
diff changeset
1849 if (interval->from() != from_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1850 // the part before from_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1851 interval = interval->split(from_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1852 interval->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
1853 append_interval(interval);
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1854 } else {
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1855 _needs_full_resort = true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1856 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1857 assert(interval->from() == from_op_id, "must be true now");
a61af66fc99e Initial load
duke
parents:
diff changeset
1858
a61af66fc99e Initial load
duke
parents:
diff changeset
1859 Interval* spilled_part = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1860 if (interval->to() != to_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1861 // the part after to_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1862 spilled_part = interval->split_from_start(to_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1863 append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1864 move_resolver.add_mapping(spilled_part, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1866 assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1867
a61af66fc99e Initial load
duke
parents:
diff changeset
1868 assert(spilled_part->from() == from_op_id && spilled_part->to() == to_op_id, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1870 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1871
a61af66fc99e Initial load
duke
parents:
diff changeset
1872 void LinearScan::resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1873 assert(block->is_set(BlockBegin::exception_entry_flag), "should not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1874 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1875
a61af66fc99e Initial load
duke
parents:
diff changeset
1876 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1877 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1878 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
1879 resolve_exception_entry(block, r, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1880 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1881
a61af66fc99e Initial load
duke
parents:
diff changeset
1882 // 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
1883 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1884 resolve_exception_entry(block, phi->operand()->vreg_number(), move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1885 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1886
a61af66fc99e Initial load
duke
parents:
diff changeset
1887 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1888 // insert moves after first instruction
5906
b279f99d7143 6910461: Register allocator may insert spill code at wrong insertion index
roland
parents: 4948
diff changeset
1889 move_resolver.set_insert_position(block->lir(), 0);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1890 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1891 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1892 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1893
a61af66fc99e Initial load
duke
parents:
diff changeset
1894
a61af66fc99e Initial load
duke
parents:
diff changeset
1895 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
1896 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1897 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1898 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1899 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1900
a61af66fc99e Initial load
duke
parents:
diff changeset
1901 // the computation of to_interval is equal to resolve_collect_mappings,
a61af66fc99e Initial load
duke
parents:
diff changeset
1902 // but from_interval is more complicated because of phi functions
a61af66fc99e Initial load
duke
parents:
diff changeset
1903 BlockBegin* to_block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1904 Interval* to_interval = interval_at_block_begin(to_block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1905
a61af66fc99e Initial load
duke
parents:
diff changeset
1906 if (phi != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1907 // phi function of the exception entry block
a61af66fc99e Initial load
duke
parents:
diff changeset
1908 // no moves are created for this phi function in the LIR_Generator, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
1909 // interval at the throwing instruction must be searched using the operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1910 // of the phi function
a61af66fc99e Initial load
duke
parents:
diff changeset
1911 Value from_value = phi->operand_at(handler->phi_operand());
a61af66fc99e Initial load
duke
parents:
diff changeset
1912
a61af66fc99e Initial load
duke
parents:
diff changeset
1913 // with phi functions it can happen that the same from_value is used in
a61af66fc99e Initial load
duke
parents:
diff changeset
1914 // multiple mappings, so notify move-resolver that this is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
1915 move_resolver.set_multiple_reads_allowed();
a61af66fc99e Initial load
duke
parents:
diff changeset
1916
a61af66fc99e Initial load
duke
parents:
diff changeset
1917 Constant* con = from_value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
1918 if (con != NULL && !con->is_pinned()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1919 // unpinned constants may have no register, so add mapping from constant to interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1920 move_resolver.add_mapping(LIR_OprFact::value_type(con->type()), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1921 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1922 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1923 Interval* from_interval = interval_at_op_id(from_value->operand()->vreg_number(), throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1924 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1925 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1926
a61af66fc99e Initial load
duke
parents:
diff changeset
1927 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1928 // no phi function, so use reg_num also for from_interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1929 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1930 Interval* from_interval = interval_at_op_id(reg_num, throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1931 if (from_interval != to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1932 // optimization to reduce number of moves: when to_interval is on stack and
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 // the stack slot is known to be always correct, then no move is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 if (!from_interval->always_in_memory() || from_interval->canonical_spill_slot() != to_interval->assigned_reg()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1935 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1939 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1940
a61af66fc99e Initial load
duke
parents:
diff changeset
1941 void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1942 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
1943
a61af66fc99e Initial load
duke
parents:
diff changeset
1944 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1945 assert(handler->lir_op_id() == -1, "already processed this xhandler");
a61af66fc99e Initial load
duke
parents:
diff changeset
1946 DEBUG_ONLY(handler->set_lir_op_id(throwing_op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 assert(handler->entry_code() == NULL, "code already present");
a61af66fc99e Initial load
duke
parents:
diff changeset
1948
a61af66fc99e Initial load
duke
parents:
diff changeset
1949 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1950 BlockBegin* block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1951 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1952 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
1953 resolve_exception_edge(handler, throwing_op_id, r, NULL, 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 // 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
1957 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1958 resolve_exception_edge(handler, throwing_op_id, phi->operand()->vreg_number(), phi, move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1959 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1960
a61af66fc99e Initial load
duke
parents:
diff changeset
1961 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1962 LIR_List* entry_code = new LIR_List(compilation());
a61af66fc99e Initial load
duke
parents:
diff changeset
1963 move_resolver.set_insert_position(entry_code, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1964 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1965
a61af66fc99e Initial load
duke
parents:
diff changeset
1966 entry_code->jump(handler->entry_block());
a61af66fc99e Initial load
duke
parents:
diff changeset
1967 handler->set_entry_code(entry_code);
a61af66fc99e Initial load
duke
parents:
diff changeset
1968 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1969 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1970
a61af66fc99e Initial load
duke
parents:
diff changeset
1971
a61af66fc99e Initial load
duke
parents:
diff changeset
1972 void LinearScan::resolve_exception_handlers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1973 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1974 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1975 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1976
a61af66fc99e Initial load
duke
parents:
diff changeset
1977 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1978 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1981 resolve_exception_entry(block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1982 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1984
a61af66fc99e Initial load
duke
parents:
diff changeset
1985 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1986 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1987 LIR_List* ops = block->lir();
a61af66fc99e Initial load
duke
parents:
diff changeset
1988 int num_ops = ops->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1989
a61af66fc99e Initial load
duke
parents:
diff changeset
1990 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1991 assert(visitor.no_operands(ops->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1992 for (int j = 1; j < num_ops; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1993 LIR_Op* op = ops->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1995
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 if (op_id != -1 && has_info(op_id)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1997 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1998 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 assert(visitor.info_count() > 0, "should not visit otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2000
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
2002 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2003 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2004 resolve_exception_edge(xhandlers->handler_at(k), op_id, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2006
a61af66fc99e Initial load
duke
parents:
diff changeset
2007 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2008 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2009 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2010 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2011 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2013 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2014 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2015 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2016
a61af66fc99e Initial load
duke
parents:
diff changeset
2017
a61af66fc99e Initial load
duke
parents:
diff changeset
2018 // ********** Phase 7: assign register numbers back to LIR
a61af66fc99e Initial load
duke
parents:
diff changeset
2019 // (includes computation of debug information and oop maps)
a61af66fc99e Initial load
duke
parents:
diff changeset
2020
a61af66fc99e Initial load
duke
parents:
diff changeset
2021 VMReg LinearScan::vm_reg_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2022 VMReg reg = interval->cached_vm_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2023 if (!reg->is_valid() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2024 reg = vm_reg_for_operand(operand_for_interval(interval));
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 interval->set_cached_vm_reg(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2027 assert(reg == vm_reg_for_operand(operand_for_interval(interval)), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2028 return reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
2029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2030
a61af66fc99e Initial load
duke
parents:
diff changeset
2031 VMReg LinearScan::vm_reg_for_operand(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2032 assert(opr->is_oop(), "currently only implemented for oop operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2033 return frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2034 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2035
a61af66fc99e Initial load
duke
parents:
diff changeset
2036
a61af66fc99e Initial load
duke
parents:
diff changeset
2037 LIR_Opr LinearScan::operand_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2038 LIR_Opr opr = interval->cached_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2039 if (opr->is_illegal()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2040 opr = calc_operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2041 interval->set_cached_opr(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2042 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2043
a61af66fc99e Initial load
duke
parents:
diff changeset
2044 assert(opr == calc_operand_for_interval(interval), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2045 return opr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2046 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2047
a61af66fc99e Initial load
duke
parents:
diff changeset
2048 LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2049 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2050 BasicType type = interval->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2051
a61af66fc99e Initial load
duke
parents:
diff changeset
2052 if (assigned_reg >= nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2053 // stack slot
a61af66fc99e Initial load
duke
parents:
diff changeset
2054 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2055 return LIR_OprFact::stack(assigned_reg - nof_regs, type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2056
a61af66fc99e Initial load
duke
parents:
diff changeset
2057 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2058 // register
a61af66fc99e Initial load
duke
parents:
diff changeset
2059 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2060 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2061 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2062 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2063 return LIR_OprFact::single_cpu_oop(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2064 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2065
1816
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2066 case T_ADDRESS: {
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2067 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
2068 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
2069 return LIR_OprFact::single_cpu_address(assigned_reg);
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2070 }
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2071
6739
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2072 case T_METADATA: {
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2073 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2074 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2075 return LIR_OprFact::single_cpu_metadata(assigned_reg);
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2076 }
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2077
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2078 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2079 case T_FLOAT: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2080 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2081 case T_INT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2082 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2083 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2084 return LIR_OprFact::single_cpu(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2085 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2086
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2087 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2088 case T_DOUBLE: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2089 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2090 case T_LONG: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2091 int assigned_regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
2092 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2093 assert(num_physical_regs(T_LONG) == 1 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 (assigned_regHi >= pd_first_cpu_reg && assigned_regHi <= pd_last_cpu_reg), "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2095
a61af66fc99e Initial load
duke
parents:
diff changeset
2096 assert(assigned_reg != assigned_regHi, "invalid allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2097 assert(num_physical_regs(T_LONG) == 1 || assigned_reg < assigned_regHi,
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 "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
2099 assert((assigned_regHi != any_reg) ^ (num_physical_regs(T_LONG) == 1), "must be match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2100 if (requires_adjacent_regs(T_LONG)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2101 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == assigned_regHi, "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2103
a61af66fc99e Initial load
duke
parents:
diff changeset
2104 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2105 return LIR_OprFact::double_cpu(assigned_reg, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2106 #else
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2107 #if defined(SPARC) || defined(PPC)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2108 return LIR_OprFact::double_cpu(assigned_regHi, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2109 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2110 return LIR_OprFact::double_cpu(assigned_reg, assigned_regHi);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2111 #endif // SPARC
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2112 #endif // LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2114
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2115 #ifndef __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2116 case T_FLOAT: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2117 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 if (UseSSE >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2119 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2121 return LIR_OprFact::single_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2123 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2124
a61af66fc99e Initial load
duke
parents:
diff changeset
2125 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2126 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2127 return LIR_OprFact::single_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2129
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 case T_DOUBLE: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2131 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2132 if (UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2133 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 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
2135 return LIR_OprFact::double_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2138
a61af66fc99e Initial load
duke
parents:
diff changeset
2139 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2140 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2141 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
2142 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2143 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
2144 #elif defined(ARM)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2145 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
2146 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
2147 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
2148 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
2149 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 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
2152 LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2153 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2154 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
2155 }
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2156 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2157
a61af66fc99e Initial load
duke
parents:
diff changeset
2158 default: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2159 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2160 return LIR_OprFact::illegalOpr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2165
a61af66fc99e Initial load
duke
parents:
diff changeset
2166 LIR_Opr LinearScan::canonical_spill_opr(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2167 assert(interval->canonical_spill_slot() >= nof_regs, "canonical spill slot not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2168 return LIR_OprFact::stack(interval->canonical_spill_slot() - nof_regs, interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2169 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2170
a61af66fc99e Initial load
duke
parents:
diff changeset
2171 LIR_Opr LinearScan::color_lir_opr(LIR_Opr opr, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2172 assert(opr->is_virtual(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2173
a61af66fc99e Initial load
duke
parents:
diff changeset
2174 Interval* interval = interval_at(opr->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
2175 assert(interval != NULL, "interval must exist");
a61af66fc99e Initial load
duke
parents:
diff changeset
2176
a61af66fc99e Initial load
duke
parents:
diff changeset
2177 if (op_id != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2178 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2179 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2180 if (block->number_of_sux() <= 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2181 // check if spill moves could have been appended at the end of this block, but
a61af66fc99e Initial load
duke
parents:
diff changeset
2182 // before the branch instruction. So the split child information for this branch would
a61af66fc99e Initial load
duke
parents:
diff changeset
2183 // be incorrect.
a61af66fc99e Initial load
duke
parents:
diff changeset
2184 LIR_OpBranch* branch = block->lir()->instructions_list()->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
2185 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2186 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2187 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
2188 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
2189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2192 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2193
a61af66fc99e Initial load
duke
parents:
diff changeset
2194 // operands are not changed when an interval is split during allocation,
a61af66fc99e Initial load
duke
parents:
diff changeset
2195 // so search the right interval here
a61af66fc99e Initial load
duke
parents:
diff changeset
2196 interval = split_child_at_op_id(interval, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2198
a61af66fc99e Initial load
duke
parents:
diff changeset
2199 LIR_Opr res = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2200
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2201 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2202 // new semantic for is_last_use: not only set on definite end of interval,
a61af66fc99e Initial load
duke
parents:
diff changeset
2203 // but also before hole
a61af66fc99e Initial load
duke
parents:
diff changeset
2204 // 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
2205 // last use information is completely correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2206 // information is only needed for fpu stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
2207 if (res->is_fpu_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2208 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
2209 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
2210 res = res->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
2211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2213 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2214
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 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
2216
a61af66fc99e Initial load
duke
parents:
diff changeset
2217 return res;
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 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2222 // some methods used to check correctness of debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2223
a61af66fc99e Initial load
duke
parents:
diff changeset
2224 void assert_no_register_values(GrowableArray<ScopeValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2225 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2226 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2227 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2228
a61af66fc99e Initial load
duke
parents:
diff changeset
2229 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 ScopeValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2231
a61af66fc99e Initial load
duke
parents:
diff changeset
2232 if (value->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 Location location = ((LocationValue*)value)->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 assert(location.where() == Location::on_stack, "value is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2238
a61af66fc99e Initial load
duke
parents:
diff changeset
2239 void assert_no_register_values(GrowableArray<MonitorValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2240 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2241 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2243
a61af66fc99e Initial load
duke
parents:
diff changeset
2244 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2245 MonitorValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2246
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 if (value->owner()->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2248 Location location = ((LocationValue*)value->owner())->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 assert(location.where() == Location::on_stack, "owner is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2251 assert(value->basic_lock().where() == Location::on_stack, "basic_lock is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2252 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2254
a61af66fc99e Initial load
duke
parents:
diff changeset
2255 void assert_equal(Location l1, Location l2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2256 assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2258
a61af66fc99e Initial load
duke
parents:
diff changeset
2259 void assert_equal(ScopeValue* v1, ScopeValue* v2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 if (v1->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2261 assert(v2->is_location(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location());
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 } else if (v1->is_constant_int()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2264 assert(v2->is_constant_int(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 assert(((ConstantIntValue*)v1)->value() == ((ConstantIntValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 } else if (v1->is_constant_double()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 assert(v2->is_constant_double(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 assert(((ConstantDoubleValue*)v1)->value() == ((ConstantDoubleValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2269 } else if (v1->is_constant_long()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2270 assert(v2->is_constant_long(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2271 assert(((ConstantLongValue*)v1)->value() == ((ConstantLongValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 } else if (v1->is_constant_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 assert(v2->is_constant_oop(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2274 assert(((ConstantOopWriteValue*)v1)->value() == ((ConstantOopWriteValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2276 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2279
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 void assert_equal(MonitorValue* m1, MonitorValue* m2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2281 assert_equal(m1->owner(), m2->owner());
a61af66fc99e Initial load
duke
parents:
diff changeset
2282 assert_equal(m1->basic_lock(), m2->basic_lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
2283 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2284
a61af66fc99e Initial load
duke
parents:
diff changeset
2285 void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2286 assert(d1->scope() == d2->scope(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2287 assert(d1->bci() == d2->bci(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2288
a61af66fc99e Initial load
duke
parents:
diff changeset
2289 if (d1->locals() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2290 assert(d1->locals() != NULL && d2->locals() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2291 assert(d1->locals()->length() == d2->locals()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2292 for (int i = 0; i < d1->locals()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2293 assert_equal(d1->locals()->at(i), d2->locals()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2295 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2296 assert(d1->locals() == NULL && d2->locals() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2298
a61af66fc99e Initial load
duke
parents:
diff changeset
2299 if (d1->expressions() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2300 assert(d1->expressions() != NULL && d2->expressions() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2301 assert(d1->expressions()->length() == d2->expressions()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2302 for (int i = 0; i < d1->expressions()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2303 assert_equal(d1->expressions()->at(i), d2->expressions()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2305 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2306 assert(d1->expressions() == NULL && d2->expressions() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2308
a61af66fc99e Initial load
duke
parents:
diff changeset
2309 if (d1->monitors() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2310 assert(d1->monitors() != NULL && d2->monitors() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2311 assert(d1->monitors()->length() == d2->monitors()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2312 for (int i = 0; i < d1->monitors()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2313 assert_equal(d1->monitors()->at(i), d2->monitors()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2315 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2316 assert(d1->monitors() == NULL && d2->monitors() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2318
a61af66fc99e Initial load
duke
parents:
diff changeset
2319 if (d1->caller() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2320 assert(d1->caller() != NULL && d2->caller() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2321 assert_equal(d1->caller(), d2->caller());
a61af66fc99e Initial load
duke
parents:
diff changeset
2322 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2323 assert(d1->caller() == NULL && d2->caller() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2324 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2326
a61af66fc99e Initial load
duke
parents:
diff changeset
2327 void check_stack_depth(CodeEmitInfo* info, int stack_end) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2328 if (info->stack()->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2329 Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2330 switch (code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2331 case Bytecodes::_ifnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2332 case Bytecodes::_ifnonnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2333 case Bytecodes::_ifeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2334 case Bytecodes::_ifne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2335 case Bytecodes::_iflt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2336 case Bytecodes::_ifge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2337 case Bytecodes::_ifgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2338 case Bytecodes::_ifle : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2339 case Bytecodes::_if_icmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2340 case Bytecodes::_if_icmpne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2341 case Bytecodes::_if_icmplt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2342 case Bytecodes::_if_icmpge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2343 case Bytecodes::_if_icmpgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2344 case Bytecodes::_if_icmple : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2345 case Bytecodes::_if_acmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2346 case Bytecodes::_if_acmpne :
a61af66fc99e Initial load
duke
parents:
diff changeset
2347 assert(stack_end >= -Bytecodes::depth(code), "must have non-empty expression stack at if bytecode");
a61af66fc99e Initial load
duke
parents:
diff changeset
2348 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2349 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2350 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2352
a61af66fc99e Initial load
duke
parents:
diff changeset
2353 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2354
a61af66fc99e Initial load
duke
parents:
diff changeset
2355
a61af66fc99e Initial load
duke
parents:
diff changeset
2356 IntervalWalker* LinearScan::init_compute_oop_maps() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2357 // setup lists of potential oops for walking
a61af66fc99e Initial load
duke
parents:
diff changeset
2358 Interval* oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2359 Interval* non_oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2360
a61af66fc99e Initial load
duke
parents:
diff changeset
2361 create_unhandled_lists(&oop_intervals, &non_oop_intervals, is_oop_interval, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2362
a61af66fc99e Initial load
duke
parents:
diff changeset
2363 // intervals that have no oops inside need not to be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
2364 // to ensure a walking until the last instruction id, add a dummy interval
a61af66fc99e Initial load
duke
parents:
diff changeset
2365 // with a high operation id
a61af66fc99e Initial load
duke
parents:
diff changeset
2366 non_oop_intervals = new Interval(any_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2367 non_oop_intervals->add_range(max_jint - 2, max_jint - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2368
a61af66fc99e Initial load
duke
parents:
diff changeset
2369 return new IntervalWalker(this, oop_intervals, non_oop_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2371
a61af66fc99e Initial load
duke
parents:
diff changeset
2372
a61af66fc99e Initial load
duke
parents:
diff changeset
2373 OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2374 TRACE_LINEAR_SCAN(3, tty->print_cr("creating oop map at op_id %d", op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2375
a61af66fc99e Initial load
duke
parents:
diff changeset
2376 // walk before the current operation -> intervals that start at
a61af66fc99e Initial load
duke
parents:
diff changeset
2377 // the operation (= output operands of the operation) are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2378 // included in the oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2379 iw->walk_before(op->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
2380
a61af66fc99e Initial load
duke
parents:
diff changeset
2381 int frame_size = frame_map()->framesize();
a61af66fc99e Initial load
duke
parents:
diff changeset
2382 int arg_count = frame_map()->oop_map_arg_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2383 OopMap* map = new OopMap(frame_size, arg_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2384
a61af66fc99e Initial load
duke
parents:
diff changeset
2385 // Check if this is a patch site.
a61af66fc99e Initial load
duke
parents:
diff changeset
2386 bool is_patch_info = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2387 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2388 assert(!is_call_site, "move must not be a call site");
a61af66fc99e Initial load
duke
parents:
diff changeset
2389 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2390 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2391
a61af66fc99e Initial load
duke
parents:
diff changeset
2392 is_patch_info = move->patch_code() != lir_patch_none;
a61af66fc99e Initial load
duke
parents:
diff changeset
2393 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2394
a61af66fc99e Initial load
duke
parents:
diff changeset
2395 // Iterate through active intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2396 for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2397 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2398
a61af66fc99e Initial load
duke
parents:
diff changeset
2399 assert(interval->current_from() <= op->id() && op->id() <= interval->current_to(), "interval should not be active otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2400 assert(interval->assigned_regHi() == any_reg, "oop must be single word");
a61af66fc99e Initial load
duke
parents:
diff changeset
2401 assert(interval->reg_num() >= LIR_OprDesc::vreg_base, "fixed interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
2402
a61af66fc99e Initial load
duke
parents:
diff changeset
2403 // Check if this range covers the instruction. Intervals that
a61af66fc99e Initial load
duke
parents:
diff changeset
2404 // start or end at the current operation are not included in the
a61af66fc99e Initial load
duke
parents:
diff changeset
2405 // oop map, except in the case of patching moves. For patching
a61af66fc99e Initial load
duke
parents:
diff changeset
2406 // moves, any intervals which end at this instruction are included
a61af66fc99e Initial load
duke
parents:
diff changeset
2407 // in the oop map since we may safepoint while doing the patch
a61af66fc99e Initial load
duke
parents:
diff changeset
2408 // before we've consumed the inputs.
a61af66fc99e Initial load
duke
parents:
diff changeset
2409 if (is_patch_info || op->id() < interval->current_to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2410
a61af66fc99e Initial load
duke
parents:
diff changeset
2411 // caller-save registers must not be included into oop-maps at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
2412 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
2413
a61af66fc99e Initial load
duke
parents:
diff changeset
2414 VMReg name = vm_reg_for_interval(interval);
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2415 set_oop(map, name);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2416
a61af66fc99e Initial load
duke
parents:
diff changeset
2417 // Spill optimization: when the stack value is guaranteed to be always correct,
a61af66fc99e Initial load
duke
parents:
diff changeset
2418 // 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
2419 if (interval->always_in_memory() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2420 op->id() > interval->spill_definition_pos() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2421 interval->assigned_reg() != interval->canonical_spill_slot()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2422 assert(interval->spill_definition_pos() > 0, "position not set correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
2423 assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
2424 assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
2425
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2426 set_oop(map, frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2430
a61af66fc99e Initial load
duke
parents:
diff changeset
2431 // add oops from lock stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2432 assert(info->stack() != NULL, "CodeEmitInfo must always have a stack");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2433 int locks_count = info->stack()->total_locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2434 for (int i = 0; i < locks_count; i++) {
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2435 set_oop(map, frame_map()->monitor_object_regname(i));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2436 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2437
a61af66fc99e Initial load
duke
parents:
diff changeset
2438 return map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2440
a61af66fc99e Initial load
duke
parents:
diff changeset
2441
a61af66fc99e Initial load
duke
parents:
diff changeset
2442 void LinearScan::compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2443 assert(visitor.info_count() > 0, "no oop map needed");
a61af66fc99e Initial load
duke
parents:
diff changeset
2444
a61af66fc99e Initial load
duke
parents:
diff changeset
2445 // compute oop_map only for first CodeEmitInfo
a61af66fc99e Initial load
duke
parents:
diff changeset
2446 // because it is (in most cases) equal for all other infos of the same operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2447 CodeEmitInfo* first_info = visitor.info_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2448 OopMap* first_oop_map = compute_oop_map(iw, op, first_info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2449
a61af66fc99e Initial load
duke
parents:
diff changeset
2450 for (int i = 0; i < visitor.info_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2451 CodeEmitInfo* info = visitor.info_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2452 OopMap* oop_map = first_oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2453
a61af66fc99e Initial load
duke
parents:
diff changeset
2454 if (info->stack()->locks_size() != first_info->stack()->locks_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2455 // this info has a different number of locks then the precomputed oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2456 // (possible for lock and unlock instructions) -> compute oop map with
a61af66fc99e Initial load
duke
parents:
diff changeset
2457 // correct lock information
a61af66fc99e Initial load
duke
parents:
diff changeset
2458 oop_map = compute_oop_map(iw, op, info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2460
a61af66fc99e Initial load
duke
parents:
diff changeset
2461 if (info->_oop_map == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2462 info->_oop_map = oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2463 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2464 // a CodeEmitInfo can not be shared between different LIR-instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2465 // because interval splitting can occur anywhere between two instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2466 // and so the oop maps must be different
a61af66fc99e Initial load
duke
parents:
diff changeset
2467 // -> check if the already set oop_map is exactly the one calculated for this operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2468 assert(info->_oop_map == oop_map, "same CodeEmitInfo used for multiple LIR instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
2469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2471 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2472
a61af66fc99e Initial load
duke
parents:
diff changeset
2473
a61af66fc99e Initial load
duke
parents:
diff changeset
2474 // frequently used constants
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2475 // Allocate them with new so they are never destroyed (otherwise, a
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2476 // forced exit could destroy these objects while they are still in
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2477 // use).
6197
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2478 ConstantOopWriteValue* LinearScan::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2479 ConstantIntValue* LinearScan::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2480 ConstantIntValue* LinearScan::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2481 ConstantIntValue* LinearScan::_int_1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2482 ConstantIntValue* LinearScan::_int_2_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2483 LocationValue* _illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2484
a61af66fc99e Initial load
duke
parents:
diff changeset
2485 void LinearScan::init_compute_debug_info() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2486 // cache for frequently used scope values
a61af66fc99e Initial load
duke
parents:
diff changeset
2487 // (cpu registers and stack slots)
a61af66fc99e Initial load
duke
parents:
diff changeset
2488 _scope_value_cache = ScopeValueArray((LinearScan::nof_cpu_regs + frame_map()->argcount() + max_spills()) * 2, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2490
a61af66fc99e Initial load
duke
parents:
diff changeset
2491 MonitorValue* LinearScan::location_for_monitor_index(int monitor_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2492 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2493 if (!frame_map()->location_for_monitor_object(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2494 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2495 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2496 ScopeValue* object_scope_value = new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2497
a61af66fc99e Initial load
duke
parents:
diff changeset
2498 if (!frame_map()->location_for_monitor_lock(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2499 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2501 return new MonitorValue(object_scope_value, loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2502 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2503
a61af66fc99e Initial load
duke
parents:
diff changeset
2504 LocationValue* LinearScan::location_for_name(int name, Location::Type loc_type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2505 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2506 if (!frame_map()->locations_for_slot(name, loc_type, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2507 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2508 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2509 return new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2511
a61af66fc99e Initial load
duke
parents:
diff changeset
2512
a61af66fc99e Initial load
duke
parents:
diff changeset
2513 int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2514 assert(opr->is_constant(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2515
a61af66fc99e Initial load
duke
parents:
diff changeset
2516 LIR_Const* c = opr->as_constant_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2517 BasicType t = c->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2518 switch (t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2519 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2520 jobject value = c->as_jobject();
a61af66fc99e Initial load
duke
parents:
diff changeset
2521 if (value == NULL) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2522 scope_values->append(_oop_null_scope_value);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2523 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2524 scope_values->append(new ConstantOopWriteValue(c->as_jobject()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2526 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2528
a61af66fc99e Initial load
duke
parents:
diff changeset
2529 case T_INT: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2530 case T_FLOAT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2531 int value = c->as_jint_bits();
a61af66fc99e Initial load
duke
parents:
diff changeset
2532 switch (value) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2533 case -1: scope_values->append(_int_m1_scope_value); break;
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2534 case 0: scope_values->append(_int_0_scope_value); break;
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2535 case 1: scope_values->append(_int_1_scope_value); break;
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2536 case 2: scope_values->append(_int_2_scope_value); break;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2537 default: scope_values->append(new ConstantIntValue(c->as_jint_bits())); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2538 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2539 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2540 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2541
a61af66fc99e Initial load
duke
parents:
diff changeset
2542 case T_LONG: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2543 case T_DOUBLE: {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2544 #ifdef _LP64
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2545 scope_values->append(_int_0_scope_value);
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2546 scope_values->append(new ConstantLongValue(c->as_jlong_bits()));
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2547 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2548 if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2549 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2550 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2551 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2552 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2553 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2554 }
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2555 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2556 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2558
1297
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2559 case T_ADDRESS: {
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2560 #ifdef _LP64
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2561 scope_values->append(new ConstantLongValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2562 #else
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2563 scope_values->append(new ConstantIntValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2564 #endif
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2565 return 1;
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2566 }
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2567
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2568 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
2569 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2570 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2571 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2573
a61af66fc99e Initial load
duke
parents:
diff changeset
2574 int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2575 if (opr->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2576 int stack_idx = opr->single_stack_ix();
a61af66fc99e Initial load
duke
parents:
diff changeset
2577 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2578 int cache_idx = (stack_idx + LinearScan::nof_cpu_regs) * 2 + (is_oop ? 1 : 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2579
a61af66fc99e Initial load
duke
parents:
diff changeset
2580 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2581 if (sv == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2582 Location::Type loc_type = is_oop ? Location::oop : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2583 sv = location_for_name(stack_idx, loc_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2584 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2586
a61af66fc99e Initial load
duke
parents:
diff changeset
2587 // check if cached value is correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2588 DEBUG_ONLY(assert_equal(sv, location_for_name(stack_idx, is_oop ? Location::oop : Location::normal)));
a61af66fc99e Initial load
duke
parents:
diff changeset
2589
a61af66fc99e Initial load
duke
parents:
diff changeset
2590 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2591 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2592
a61af66fc99e Initial load
duke
parents:
diff changeset
2593 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2594 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2595 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
2596 Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2597
a61af66fc99e Initial load
duke
parents:
diff changeset
2598 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2599 if (sv == NULL) {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2600 Location::Type loc_type = is_oop ? Location::oop : int_loc_type;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2601 VMReg rname = frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2602 sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2603 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2605
a61af66fc99e Initial load
duke
parents:
diff changeset
2606 // check if cached value is correct
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2607 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
2608
a61af66fc99e Initial load
duke
parents:
diff changeset
2609 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2610 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2611
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2612 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2613 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2614 VMReg rname = opr->as_xmm_float_reg()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2615 LocationValue* sv = new LocationValue(Location::new_reg_loc(Location::normal, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2616
a61af66fc99e Initial load
duke
parents:
diff changeset
2617 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2618 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2619 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2620
a61af66fc99e Initial load
duke
parents:
diff changeset
2621 } else if (opr->is_single_fpu()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2622 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2623 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2624 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2625 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2626 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
2627 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2628 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2629 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2630
a61af66fc99e Initial load
duke
parents:
diff changeset
2631 Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2632 VMReg rname = frame_map()->fpu_regname(opr->fpu_regnr());
3999
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2633 #ifndef __SOFTFP__
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2634 #ifndef VM_LITTLE_ENDIAN
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2635 if (! float_saved_as_double) {
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2636 // On big endian system, we may have an issue if float registers use only
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2637 // the low half of the (same) double registers.
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2638 // Both the float and the double could have the same regnr but would correspond
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2639 // to two different addresses once saved.
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2640
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2641 // get next safely (no assertion checks)
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2642 VMReg next = VMRegImpl::as_VMReg(1+rname->value());
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2643 if (next->is_reg() &&
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2644 (next->as_FloatRegister() == rname->as_FloatRegister())) {
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2645 // the back-end does use the same numbering for the double and the float
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2646 rname = next; // VMReg for the low bits, e.g. the real VMReg for the float
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2647 }
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2648 }
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2649 #endif
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2650 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2651 LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2652
a61af66fc99e Initial load
duke
parents:
diff changeset
2653 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2654 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2655
a61af66fc99e Initial load
duke
parents:
diff changeset
2656 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2657 // double-size operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2658
a61af66fc99e Initial load
duke
parents:
diff changeset
2659 ScopeValue* first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2660 ScopeValue* second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2661
a61af66fc99e Initial load
duke
parents:
diff changeset
2662 if (opr->is_double_stack()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2663 #ifdef _LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2664 Location loc1;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2665 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
2666 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
2667 bailout("too large frame");
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2668 }
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2669 // Does this reverse on x86 vs. sparc?
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2670 first = new LocationValue(loc1);
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2671 second = _int_0_scope_value;
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2672 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2673 Location loc1, loc2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2674 if (!frame_map()->locations_for_slot(opr->double_stack_ix(), Location::normal, &loc1, &loc2)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2675 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2676 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2677 first = new LocationValue(loc1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2678 second = new LocationValue(loc2);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2679 #endif // _LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2680
a61af66fc99e Initial load
duke
parents:
diff changeset
2681 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2682 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2683 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2684 first = new LocationValue(Location::new_reg_loc(Location::lng, rname_first));
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2685 second = _int_0_scope_value;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2686 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2687 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2688 VMReg rname_second = opr->as_register_hi()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2689
a61af66fc99e Initial load
duke
parents:
diff changeset
2690 if (hi_word_offset_in_bytes < lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2691 // lo/hi and swapped relative to first and second, so swap them
a61af66fc99e Initial load
duke
parents:
diff changeset
2692 VMReg tmp = rname_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2693 rname_first = rname_second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2694 rname_second = tmp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2695 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2696
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 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
2699 #endif //_LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2700
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2701
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2702 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2703 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2704 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2705 VMReg rname_first = opr->as_xmm_double_reg()->as_VMReg();
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2706 # ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2707 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2708 second = _int_0_scope_value;
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2709 # else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2710 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2711 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2712 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2713 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2714 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2715 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2716 # endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2717 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2718
a61af66fc99e Initial load
duke
parents:
diff changeset
2719 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2720 // 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
2721 // the double as float registers in the native ordering. On X86,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2722 // fpu_regnrLo is a FPU stack slot whose VMReg represents
a61af66fc99e Initial load
duke
parents:
diff changeset
2723 // the low-order word of the double and fpu_regnrLo + 1 is the
a61af66fc99e Initial load
duke
parents:
diff changeset
2724 // name for the other half. *first and *second must represent the
a61af66fc99e Initial load
duke
parents:
diff changeset
2725 // least and most significant words, respectively.
a61af66fc99e Initial load
duke
parents:
diff changeset
2726
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2727 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2728 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2729 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2730 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2731 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
2732 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2733 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2734
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2735 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrLo is used)");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2736 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2737 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2738 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2739 #endif
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2740 #ifdef ARM
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2741 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
2742 #endif
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2743 #ifdef PPC
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2744 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
2745 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2746
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2747 #ifdef VM_LITTLE_ENDIAN
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2748 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrLo());
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2749 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2750 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi());
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2751 #endif
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2752
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2753 #ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2754 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2755 second = _int_0_scope_value;
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2756 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2757 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2758 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2759 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2760 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2761 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2762 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2763 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2764
a61af66fc99e Initial load
duke
parents:
diff changeset
2765 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2766 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2767 first = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2768 second = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2769 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2770
a61af66fc99e Initial load
duke
parents:
diff changeset
2771 assert(first != NULL && second != NULL, "must be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2772 // The convention the interpreter uses is that the second local
a61af66fc99e Initial load
duke
parents:
diff changeset
2773 // holds the first raw word of the native double representation.
a61af66fc99e Initial load
duke
parents:
diff changeset
2774 // This is actually reasonable, since locals and stack arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2775 // grow downwards in all implementations.
a61af66fc99e Initial load
duke
parents:
diff changeset
2776 // (If, on some machine, the interpreter's Java locals or stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2777 // were to grow upwards, the embedded doubles would be word-swapped.)
a61af66fc99e Initial load
duke
parents:
diff changeset
2778 scope_values->append(second);
a61af66fc99e Initial load
duke
parents:
diff changeset
2779 scope_values->append(first);
a61af66fc99e Initial load
duke
parents:
diff changeset
2780 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2781 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2783
a61af66fc99e Initial load
duke
parents:
diff changeset
2784
a61af66fc99e Initial load
duke
parents:
diff changeset
2785 int LinearScan::append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2786 if (value != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2787 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
2788 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
2789
a61af66fc99e Initial load
duke
parents:
diff changeset
2790 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
2791 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2792
a61af66fc99e Initial load
duke
parents:
diff changeset
2793 if (con != NULL && !con->is_pinned() && !opr->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2794 // Unpinned constants may have a virtual operand for a part of the lifetime
a61af66fc99e Initial load
duke
parents:
diff changeset
2795 // or may be illegal when it was optimized away,
a61af66fc99e Initial load
duke
parents:
diff changeset
2796 // so always use a constant operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2797 opr = LIR_OprFact::value_type(con->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2799 assert(opr->is_virtual() || opr->is_constant(), "other cases not allowed here");
a61af66fc99e Initial load
duke
parents:
diff changeset
2800
a61af66fc99e Initial load
duke
parents:
diff changeset
2801 if (opr->is_virtual()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2802 LIR_OpVisitState::OprMode mode = LIR_OpVisitState::inputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2803
a61af66fc99e Initial load
duke
parents:
diff changeset
2804 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2805 if (block->number_of_sux() == 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2806 // generating debug information for the last instruction of a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
2807 // if this instruction is a branch, spill moves are inserted before this branch
a61af66fc99e Initial load
duke
parents:
diff changeset
2808 // and so the wrong operand would be returned (spill moves at block boundaries are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2809 // considered in the live ranges of intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
2810 // Solution: use the first op_id of the branch target block instead.
a61af66fc99e Initial load
duke
parents:
diff changeset
2811 if (block->lir()->instructions_list()->last()->as_OpBranch() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2812 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2813 op_id = block->sux_at(0)->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2814 mode = LIR_OpVisitState::outputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2818
a61af66fc99e Initial load
duke
parents:
diff changeset
2819 // Get current location of operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2820 // The operand must be live because debug information is considered when building the intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2821 // if the interval is not live, color_lir_opr will cause an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
2822 opr = color_lir_opr(opr, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2823 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
2824
a61af66fc99e Initial load
duke
parents:
diff changeset
2825 // Append to ScopeValue array
a61af66fc99e Initial load
duke
parents:
diff changeset
2826 return append_scope_value_for_operand(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2827
a61af66fc99e Initial load
duke
parents:
diff changeset
2828 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2829 assert(value->as_Constant() != NULL, "all other instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2830 assert(opr->is_constant(), "operand must be constant");
a61af66fc99e Initial load
duke
parents:
diff changeset
2831
a61af66fc99e Initial load
duke
parents:
diff changeset
2832 return append_scope_value_for_constant(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2834 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2835 // append a dummy value because real value not needed
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2836 scope_values->append(_illegal_value);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2837 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2838 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2839 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2840
a61af66fc99e Initial load
duke
parents:
diff changeset
2841
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2842 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
2843 IRScopeDebugInfo* caller_debug_info = NULL;
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2844
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2845 ValueStack* caller_state = cur_state->caller_state();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2846 if (caller_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2847 // process recursively to compute outermost scope first
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2848 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
2849 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2850
a61af66fc99e Initial load
duke
parents:
diff changeset
2851 // initialize these to null.
a61af66fc99e Initial load
duke
parents:
diff changeset
2852 // If we don't need deopt info or there are no locals, expressions or monitors,
a61af66fc99e Initial load
duke
parents:
diff changeset
2853 // then these get recorded as no information and avoids the allocation of 0 length arrays.
a61af66fc99e Initial load
duke
parents:
diff changeset
2854 GrowableArray<ScopeValue*>* locals = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2855 GrowableArray<ScopeValue*>* expressions = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2856 GrowableArray<MonitorValue*>* monitors = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2857
a61af66fc99e Initial load
duke
parents:
diff changeset
2858 // describe local variable values
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2859 int nof_locals = cur_state->locals_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2860 if (nof_locals > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2861 locals = new GrowableArray<ScopeValue*>(nof_locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2862
a61af66fc99e Initial load
duke
parents:
diff changeset
2863 int pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2864 while (pos < nof_locals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2865 assert(pos < cur_state->locals_size(), "why not?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2866
a61af66fc99e Initial load
duke
parents:
diff changeset
2867 Value local = cur_state->local_at(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2868 pos += append_scope_value(op_id, local, locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2869
a61af66fc99e Initial load
duke
parents:
diff changeset
2870 assert(locals->length() == pos, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2871 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2872 assert(locals->length() == cur_scope->method()->max_locals(), "wrong number of locals");
a61af66fc99e Initial load
duke
parents:
diff changeset
2873 assert(locals->length() == cur_state->locals_size(), "wrong number of locals");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2874 } else if (cur_scope->method()->max_locals() > 0) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2875 assert(cur_state->kind() == ValueStack::EmptyExceptionState, "should be");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2876 nof_locals = cur_scope->method()->max_locals();
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2877 locals = new GrowableArray<ScopeValue*>(nof_locals);
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2878 for(int i = 0; i < nof_locals; i++) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2879 locals->append(_illegal_value);
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2880 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2881 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2882
a61af66fc99e Initial load
duke
parents:
diff changeset
2883 // describe expression stack
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2884 int nof_stack = cur_state->stack_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2885 if (nof_stack > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2886 expressions = new GrowableArray<ScopeValue*>(nof_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
2887
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2888 int pos = 0;
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2889 while (pos < nof_stack) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2890 Value expression = cur_state->stack_at_inc(pos);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2891 append_scope_value(op_id, expression, expressions);
a61af66fc99e Initial load
duke
parents:
diff changeset
2892
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2893 assert(expressions->length() == pos, "must match");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2894 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2895 assert(expressions->length() == cur_state->stack_size(), "wrong number of stack entries");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2897
a61af66fc99e Initial load
duke
parents:
diff changeset
2898 // describe monitors
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2899 int nof_locks = cur_state->locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2900 if (nof_locks > 0) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2901 int lock_offset = cur_state->caller_state() != NULL ? cur_state->caller_state()->total_locks_size() : 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2902 monitors = new GrowableArray<MonitorValue*>(nof_locks);
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2903 for (int i = 0; i < nof_locks; i++) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2904 monitors->append(location_for_monitor_index(lock_offset + i));
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2905 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2906 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2907
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2908 return new IRScopeDebugInfo(cur_scope, cur_state->bci(), locals, expressions, monitors, caller_debug_info);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2910
a61af66fc99e Initial load
duke
parents:
diff changeset
2911
a61af66fc99e Initial load
duke
parents:
diff changeset
2912 void LinearScan::compute_debug_info(CodeEmitInfo* info, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2913 TRACE_LINEAR_SCAN(3, tty->print_cr("creating debug information at op_id %d", op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
2914
a61af66fc99e Initial load
duke
parents:
diff changeset
2915 IRScope* innermost_scope = info->scope();
a61af66fc99e Initial load
duke
parents:
diff changeset
2916 ValueStack* innermost_state = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
2917
a61af66fc99e Initial load
duke
parents:
diff changeset
2918 assert(innermost_scope != NULL && innermost_state != NULL, "why is it missing?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2919
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2920 DEBUG_ONLY(check_stack_depth(info, innermost_state->stack_size()));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2921
a61af66fc99e Initial load
duke
parents:
diff changeset
2922 if (info->_scope_debug_info == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2923 // compute debug information
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2924 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
2925 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2926 // 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
2927 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
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
a61af66fc99e Initial load
duke
parents:
diff changeset
2932 void LinearScan::assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2933 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
2934 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2935 bool has_dead = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2936
a61af66fc99e Initial load
duke
parents:
diff changeset
2937 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2938 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
2939 if (op == NULL) { // this can happen when spill-moves are removed in eliminate_spill_moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2940 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2941 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
2942 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2943 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2944
a61af66fc99e Initial load
duke
parents:
diff changeset
2945 // visit instruction to get list of operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2946 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2947
a61af66fc99e Initial load
duke
parents:
diff changeset
2948 // iterate all modes of the visitor and process all virtual operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2949 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2950 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2951 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2952 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2953 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2954 visitor.set_opr_at(mode, k, color_lir_opr(opr, op_id, mode));
a61af66fc99e Initial load
duke
parents:
diff changeset
2955 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2956 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2958
a61af66fc99e Initial load
duke
parents:
diff changeset
2959 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2960 // exception handling
a61af66fc99e Initial load
duke
parents:
diff changeset
2961 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2962 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
2963 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2964 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2965 XHandler* handler = xhandlers->handler_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2966 if (handler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2967 assign_reg_num(handler->entry_code()->instructions_list(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2968 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2969 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2970 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2971 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2972 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2973
a61af66fc99e Initial load
duke
parents:
diff changeset
2974 // compute oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2975 assert(iw != NULL, "needed for compute_oop_map");
a61af66fc99e Initial load
duke
parents:
diff changeset
2976 compute_oop_map(iw, visitor, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2977
a61af66fc99e Initial load
duke
parents:
diff changeset
2978 // compute debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2979 if (!use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2980 // compute debug information if fpu stack allocation is not needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2981 // when fpu stack allocation is needed, the debug information can not
a61af66fc99e Initial load
duke
parents:
diff changeset
2982 // be computed here because the exact location of fpu operands is not known
a61af66fc99e Initial load
duke
parents:
diff changeset
2983 // -> debug information is created inside the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
2984 int n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2985 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2986 compute_debug_info(visitor.info_at(k), op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2987 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2988 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2989 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2990
a61af66fc99e Initial load
duke
parents:
diff changeset
2991 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2992 // make sure we haven't made the op invalid.
a61af66fc99e Initial load
duke
parents:
diff changeset
2993 op->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2994 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2995
a61af66fc99e Initial load
duke
parents:
diff changeset
2996 // remove useless moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2997 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2998 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2999 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
3000 LIR_Opr src = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3001 LIR_Opr dst = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3002 if (dst == src ||
a61af66fc99e Initial load
duke
parents:
diff changeset
3003 !dst->is_pointer() && !src->is_pointer() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
3004 src->is_same_register(dst)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3005 instructions->at_put(j, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3006 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3007 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3009 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3010
a61af66fc99e Initial load
duke
parents:
diff changeset
3011 if (has_dead) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3012 // iterate all instructions of the block and remove all null-values.
a61af66fc99e Initial load
duke
parents:
diff changeset
3013 int insert_point = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3014 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3015 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3016 if (op != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3017 if (insert_point != j) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3018 instructions->at_put(insert_point, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3020 insert_point++;
a61af66fc99e Initial load
duke
parents:
diff changeset
3021 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3022 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3023 instructions->truncate(insert_point);
a61af66fc99e Initial load
duke
parents:
diff changeset
3024 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3025 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3026
a61af66fc99e Initial load
duke
parents:
diff changeset
3027 void LinearScan::assign_reg_num() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3028 TIME_LINEAR_SCAN(timer_assign_reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
3029
a61af66fc99e Initial load
duke
parents:
diff changeset
3030 init_compute_debug_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
3031 IntervalWalker* iw = init_compute_oop_maps();
a61af66fc99e Initial load
duke
parents:
diff changeset
3032
a61af66fc99e Initial load
duke
parents:
diff changeset
3033 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3034 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3035 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3036 assign_reg_num(block->lir()->instructions_list(), iw);
a61af66fc99e Initial load
duke
parents:
diff changeset
3037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3039
a61af66fc99e Initial load
duke
parents:
diff changeset
3040
a61af66fc99e Initial load
duke
parents:
diff changeset
3041 void LinearScan::do_linear_scan() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3042 NOT_PRODUCT(_total_timer.begin_method());
a61af66fc99e Initial load
duke
parents:
diff changeset
3043
a61af66fc99e Initial load
duke
parents:
diff changeset
3044 number_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
3045
a61af66fc99e Initial load
duke
parents:
diff changeset
3046 NOT_PRODUCT(print_lir(1, "Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3047
a61af66fc99e Initial load
duke
parents:
diff changeset
3048 compute_local_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
3049 compute_global_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
3050 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3051
a61af66fc99e Initial load
duke
parents:
diff changeset
3052 build_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3053 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3054 sort_intervals_before_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
3055
a61af66fc99e Initial load
duke
parents:
diff changeset
3056 NOT_PRODUCT(print_intervals("Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3057 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_before_alloc));
a61af66fc99e Initial load
duke
parents:
diff changeset
3058
a61af66fc99e Initial load
duke
parents:
diff changeset
3059 allocate_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3060 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3061
a61af66fc99e Initial load
duke
parents:
diff changeset
3062 resolve_data_flow();
a61af66fc99e Initial load
duke
parents:
diff changeset
3063 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3064 resolve_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3065 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3066 // fill in number of spill slots into frame_map
a61af66fc99e Initial load
duke
parents:
diff changeset
3067 propagate_spill_slots();
a61af66fc99e Initial load
duke
parents:
diff changeset
3068 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3069
a61af66fc99e Initial load
duke
parents:
diff changeset
3070 NOT_PRODUCT(print_intervals("After Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3071 NOT_PRODUCT(print_lir(2, "LIR after register allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3072
a61af66fc99e Initial load
duke
parents:
diff changeset
3073 sort_intervals_after_allocation();
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3074
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3075 DEBUG_ONLY(verify());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3076
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3077 eliminate_spill_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
3078 assign_reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
3079 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3080
a61af66fc99e Initial load
duke
parents:
diff changeset
3081 NOT_PRODUCT(print_lir(2, "LIR after assignment of register numbers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3082 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_after_asign));
a61af66fc99e Initial load
duke
parents:
diff changeset
3083
a61af66fc99e Initial load
duke
parents:
diff changeset
3084 { TIME_LINEAR_SCAN(timer_allocate_fpu_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
3085
a61af66fc99e Initial load
duke
parents:
diff changeset
3086 if (use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3087 allocate_fpu_stack(); // Only has effect on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
3088 NOT_PRODUCT(print_lir(2, "LIR after FPU stack allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3089 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3090 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3091
a61af66fc99e Initial load
duke
parents:
diff changeset
3092 { TIME_LINEAR_SCAN(timer_optimize_lir);
a61af66fc99e Initial load
duke
parents:
diff changeset
3093
a61af66fc99e Initial load
duke
parents:
diff changeset
3094 EdgeMoveOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3095 ControlFlowOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3096 // check that cfg is still correct after optimizations
a61af66fc99e Initial load
duke
parents:
diff changeset
3097 ir()->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
3098 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3099
a61af66fc99e Initial load
duke
parents:
diff changeset
3100 NOT_PRODUCT(print_lir(1, "Before Code Generation", false));
a61af66fc99e Initial load
duke
parents:
diff changeset
3101 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final));
a61af66fc99e Initial load
duke
parents:
diff changeset
3102 NOT_PRODUCT(_total_timer.end_method(this));
a61af66fc99e Initial load
duke
parents:
diff changeset
3103 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3104
a61af66fc99e Initial load
duke
parents:
diff changeset
3105
a61af66fc99e Initial load
duke
parents:
diff changeset
3106 // ********** Printing functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3107
a61af66fc99e Initial load
duke
parents:
diff changeset
3108 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3109
a61af66fc99e Initial load
duke
parents:
diff changeset
3110 void LinearScan::print_timers(double total) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3111 _total_timer.print(total);
a61af66fc99e Initial load
duke
parents:
diff changeset
3112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3113
a61af66fc99e Initial load
duke
parents:
diff changeset
3114 void LinearScan::print_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3115 _stat_before_alloc.print("before allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3116 _stat_after_asign.print("after assignment of register");
a61af66fc99e Initial load
duke
parents:
diff changeset
3117 _stat_final.print("after optimization");
a61af66fc99e Initial load
duke
parents:
diff changeset
3118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3119
a61af66fc99e Initial load
duke
parents:
diff changeset
3120 void LinearScan::print_bitmap(BitMap& b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3121 for (unsigned int i = 0; i < b.size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3122 if (b.at(i)) tty->print("%d ", i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3124 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3126
a61af66fc99e Initial load
duke
parents:
diff changeset
3127 void LinearScan::print_intervals(const char* label) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3128 if (TraceLinearScanLevel >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3129 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3130 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3131 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3132
a61af66fc99e Initial load
duke
parents:
diff changeset
3133 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3134 Interval* interval = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3135 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3136 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
3137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3139
a61af66fc99e Initial load
duke
parents:
diff changeset
3140 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3141 tty->print_cr("--- Basic Blocks ---");
a61af66fc99e Initial load
duke
parents:
diff changeset
3142 for (i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3143 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3144 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
3145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3146 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3147 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3149
a61af66fc99e Initial load
duke
parents:
diff changeset
3150 if (PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3151 CFGPrinter::print_intervals(&_intervals, label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3154
a61af66fc99e Initial load
duke
parents:
diff changeset
3155 void LinearScan::print_lir(int level, const char* label, bool hir_valid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3156 if (TraceLinearScanLevel >= level) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3157 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3158 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3159 print_LIR(ir()->linear_scan_order());
a61af66fc99e Initial load
duke
parents:
diff changeset
3160 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3162
a61af66fc99e Initial load
duke
parents:
diff changeset
3163 if (level == 1 && PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3164 CFGPrinter::print_cfg(ir()->linear_scan_order(), label, hir_valid, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3167
a61af66fc99e Initial load
duke
parents:
diff changeset
3168 #endif //PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3169
a61af66fc99e Initial load
duke
parents:
diff changeset
3170
a61af66fc99e Initial load
duke
parents:
diff changeset
3171 // ********** verification functions for allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
3172 // (check that all intervals have a correct register and that no registers are overwritten)
a61af66fc99e Initial load
duke
parents:
diff changeset
3173 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3174
a61af66fc99e Initial load
duke
parents:
diff changeset
3175 void LinearScan::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3176 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying intervals ******************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3177 verify_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3178
a61af66fc99e Initial load
duke
parents:
diff changeset
3179 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that no oops are in fixed intervals ****************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3180 verify_no_oops_in_fixed_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3181
a61af66fc99e Initial load
duke
parents:
diff changeset
3182 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that unpinned constants are not alive across block boundaries"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3183 verify_constants();
a61af66fc99e Initial load
duke
parents:
diff changeset
3184
a61af66fc99e Initial load
duke
parents:
diff changeset
3185 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying register allocation ********************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3186 verify_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3187
a61af66fc99e Initial load
duke
parents:
diff changeset
3188 TRACE_LINEAR_SCAN(2, tty->print_cr("********* no errors found **********************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3190
a61af66fc99e Initial load
duke
parents:
diff changeset
3191 void LinearScan::verify_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3192 int len = interval_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3193 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3194
a61af66fc99e Initial load
duke
parents:
diff changeset
3195 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3196 Interval* i1 = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3197 if (i1 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3198
a61af66fc99e Initial load
duke
parents:
diff changeset
3199 i1->check_split_children();
a61af66fc99e Initial load
duke
parents:
diff changeset
3200
a61af66fc99e Initial load
duke
parents:
diff changeset
3201 if (i1->reg_num() != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3202 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
3203 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3205
a61af66fc99e Initial load
duke
parents:
diff changeset
3206 if (i1->reg_num() >= LIR_OprDesc::vreg_base && i1->type() == T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3207 tty->print_cr("Interval %d has no type assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3208 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3210
a61af66fc99e Initial load
duke
parents:
diff changeset
3211 if (i1->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3212 tty->print_cr("Interval %d has no register assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3213 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3215
a61af66fc99e Initial load
duke
parents:
diff changeset
3216 if (i1->assigned_reg() == i1->assigned_regHi()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3217 tty->print_cr("Interval %d: low and high register equal", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3218 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3220
a61af66fc99e Initial load
duke
parents:
diff changeset
3221 if (!is_processed_reg_num(i1->assigned_reg())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3222 tty->print_cr("Can not have an Interval for an ignored register"); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3223 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3225
a61af66fc99e Initial load
duke
parents:
diff changeset
3226 if (i1->first() == Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3227 tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3228 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3229 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3230
a61af66fc99e Initial load
duke
parents:
diff changeset
3231 for (Range* r = i1->first(); r != Range::end(); r = r->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3232 if (r->from() >= r->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3233 tty->print_cr("Interval %d has zero length range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3234 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3237
a61af66fc99e Initial load
duke
parents:
diff changeset
3238 for (int j = i + 1; j < len; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3239 Interval* i2 = interval_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3240 if (i2 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3241
a61af66fc99e Initial load
duke
parents:
diff changeset
3242 // special intervals that are created in MoveResolver
a61af66fc99e Initial load
duke
parents:
diff changeset
3243 // -> ignore them because the range information has no meaning there
a61af66fc99e Initial load
duke
parents:
diff changeset
3244 if (i1->from() == 1 && i1->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3245 if (i2->from() == 1 && i2->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3246
a61af66fc99e Initial load
duke
parents:
diff changeset
3247 int r1 = i1->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3248 int r1Hi = i1->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3249 int r2 = i2->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3250 int r2Hi = i2->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3251 if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3252 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
3253 i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3254 i2->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3255 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3256 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3259
a61af66fc99e Initial load
duke
parents:
diff changeset
3260 assert(has_error == false, "register allocation invalid");
a61af66fc99e Initial load
duke
parents:
diff changeset
3261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3262
a61af66fc99e Initial load
duke
parents:
diff changeset
3263
a61af66fc99e Initial load
duke
parents:
diff changeset
3264 void LinearScan::verify_no_oops_in_fixed_intervals() {
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3265 Interval* fixed_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3266 Interval* other_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3267 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
3268
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3269 // 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
3270 // with a high operation id
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3271 other_intervals = new Interval(any_reg);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3272 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
3273 IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals);
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 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3276 for (int i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3277 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3278
a61af66fc99e Initial load
duke
parents:
diff changeset
3279 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
3280
a61af66fc99e Initial load
duke
parents:
diff changeset
3281 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3282 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3283 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
3284
a61af66fc99e Initial load
duke
parents:
diff changeset
3285 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3286
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3287 if (visitor.info_count() > 0) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3288 iw->walk_before(op->id());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3289 bool check_live = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3290 if (op->code() == lir_move) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3291 LIR_Op1* move = (LIR_Op1*)op;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3292 check_live = (move->patch_code() == lir_patch_none);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3293 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3294 LIR_OpBranch* branch = op->as_OpBranch();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3295 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
3296 // 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
3297 // exception stub will never return to normal control flow.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3298 check_live = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3299 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3300
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3301 // 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
3302 // oopmap since we can't handle that correctly.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3303 if (check_live) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3304 for (Interval* interval = iw->active_first(fixedKind);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3305 interval != Interval::end();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3306 interval = interval->next()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3307 if (interval->current_to() > op->id() + 1) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3308 // 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
3309 // that this interval represents some value that's
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3310 // 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
3311 bool ok = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3312 for_each_visitor_mode(mode) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3313 int n = visitor.opr_count(mode);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3314 for (int k = 0; k < n; k++) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3315 LIR_Opr opr = visitor.opr_at(mode, k);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3316 if (opr->is_fixed_cpu()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3317 if (interval_at(reg_num(opr)) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3318 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3319 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3320 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3321 int hi = reg_numHi(opr);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3322 if (hi != -1 && interval_at(hi) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3323 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3324 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3325 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3326 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3327 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3328 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3329 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
3330 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3331 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3332 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3333 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3334
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3335 // oop-maps at calls do not contain registers, so check is not needed
a61af66fc99e Initial load
duke
parents:
diff changeset
3336 if (!visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3337
a61af66fc99e Initial load
duke
parents:
diff changeset
3338 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3339 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3340 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3341 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
3342
a61af66fc99e Initial load
duke
parents:
diff changeset
3343 if (opr->is_fixed_cpu() && opr->is_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3344 // operand is a non-virtual cpu register and contains an oop
a61af66fc99e Initial load
duke
parents:
diff changeset
3345 TRACE_LINEAR_SCAN(4, op->print_on(tty); tty->print("checking operand "); opr->print(); tty->cr());
a61af66fc99e Initial load
duke
parents:
diff changeset
3346
a61af66fc99e Initial load
duke
parents:
diff changeset
3347 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3348 assert(interval != NULL, "no interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
3349
a61af66fc99e Initial load
duke
parents:
diff changeset
3350 if (mode == LIR_OpVisitState::inputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3351 if (interval->to() >= op_id + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3352 assert(interval->to() < op_id + 2 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
3353 interval->has_hole_between(op_id, op_id + 2),
a61af66fc99e Initial load
duke
parents:
diff changeset
3354 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3355 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3356 } else if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3357 if (interval->from() <= op_id - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3358 assert(interval->has_hole_between(op_id - 1, op_id),
a61af66fc99e Initial load
duke
parents:
diff changeset
3359 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3361 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3362 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3363 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3364 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3365 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3367 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3369
a61af66fc99e Initial load
duke
parents:
diff changeset
3370
a61af66fc99e Initial load
duke
parents:
diff changeset
3371 void LinearScan::verify_constants() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3372 int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
3373 int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
3374 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3375
a61af66fc99e Initial load
duke
parents:
diff changeset
3376 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3377 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3378 BitMap live_at_edge = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
3379
a61af66fc99e Initial load
duke
parents:
diff changeset
3380 // 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
3381 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
3382 TRACE_LINEAR_SCAN(4, tty->print("checking interval %d of block B%d", r, block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3383
a61af66fc99e Initial load
duke
parents:
diff changeset
3384 Value value = gen()->instruction_for_vreg(r);
a61af66fc99e Initial load
duke
parents:
diff changeset
3385
a61af66fc99e Initial load
duke
parents:
diff changeset
3386 assert(value != NULL, "all intervals live across block boundaries must have Value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3387 assert(value->operand()->is_register() && value->operand()->is_virtual(), "value must have virtual operand");
a61af66fc99e Initial load
duke
parents:
diff changeset
3388 assert(value->operand()->vreg_number() == r, "register number must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
3389 // 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
3390 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3391 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3393
a61af66fc99e Initial load
duke
parents:
diff changeset
3394
a61af66fc99e Initial load
duke
parents:
diff changeset
3395 class RegisterVerifier: public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
3396 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
3397 LinearScan* _allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
3398 BlockList _work_list; // all blocks that must be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3399 IntervalsList _saved_states; // saved information of previous check
a61af66fc99e Initial load
duke
parents:
diff changeset
3400
a61af66fc99e Initial load
duke
parents:
diff changeset
3401 // simplified access to methods of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
3402 Compilation* compilation() const { return _allocator->compilation(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3403 Interval* interval_at(int reg_num) const { return _allocator->interval_at(reg_num); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3404 int reg_num(LIR_Opr opr) const { return _allocator->reg_num(opr); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3405
a61af66fc99e Initial load
duke
parents:
diff changeset
3406 // currently, only registers are processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3407 int state_size() { return LinearScan::nof_regs; }
a61af66fc99e Initial load
duke
parents:
diff changeset
3408
a61af66fc99e Initial load
duke
parents:
diff changeset
3409 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
3410 IntervalList* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3411 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
3412 void add_to_work_list(BlockBegin* block) { if (!_work_list.contains(block)) _work_list.append(block); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3413
a61af66fc99e Initial load
duke
parents:
diff changeset
3414 // helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3415 IntervalList* copy(IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3416 void state_put(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3417 bool check_state(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3418
a61af66fc99e Initial load
duke
parents:
diff changeset
3419 void process_block(BlockBegin* block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3420 void process_xhandler(XHandler* xhandler, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3421 void process_successor(BlockBegin* block, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3422 void process_operations(LIR_List* ops, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3423
a61af66fc99e Initial load
duke
parents:
diff changeset
3424 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
3425 RegisterVerifier(LinearScan* allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3426 : _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3427 , _work_list(16)
a61af66fc99e Initial load
duke
parents:
diff changeset
3428 , _saved_states(BlockBegin::number_of_blocks(), NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
3429 { }
a61af66fc99e Initial load
duke
parents:
diff changeset
3430
a61af66fc99e Initial load
duke
parents:
diff changeset
3431 void verify(BlockBegin* start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3432 };
a61af66fc99e Initial load
duke
parents:
diff changeset
3433
a61af66fc99e Initial load
duke
parents:
diff changeset
3434
a61af66fc99e Initial load
duke
parents:
diff changeset
3435 // entry function from LinearScan that starts the verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3436 void LinearScan::verify_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3437 RegisterVerifier verifier(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
3438 verifier.verify(block_at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
3439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3440
a61af66fc99e Initial load
duke
parents:
diff changeset
3441
a61af66fc99e Initial load
duke
parents:
diff changeset
3442 void RegisterVerifier::verify(BlockBegin* start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3443 // setup input registers (method arguments) for first block
a61af66fc99e Initial load
duke
parents:
diff changeset
3444 IntervalList* input_state = new IntervalList(state_size(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3445 CallingConvention* args = compilation()->frame_map()->incoming_arguments();
a61af66fc99e Initial load
duke
parents:
diff changeset
3446 for (int n = 0; n < args->length(); n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3447 LIR_Opr opr = args->at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
3448 if (opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3449 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3450
a61af66fc99e Initial load
duke
parents:
diff changeset
3451 if (interval->assigned_reg() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3452 input_state->at_put(interval->assigned_reg(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3453 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3454 if (interval->assigned_regHi() != LinearScan::any_reg && interval->assigned_regHi() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3455 input_state->at_put(interval->assigned_regHi(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3458 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3459
a61af66fc99e Initial load
duke
parents:
diff changeset
3460 set_state_for_block(start, input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3461 add_to_work_list(start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3462
a61af66fc99e Initial load
duke
parents:
diff changeset
3463 // main loop for verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3464 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
3465 BlockBegin* block = _work_list.at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3466 _work_list.remove_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3467
a61af66fc99e Initial load
duke
parents:
diff changeset
3468 process_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3469 } while (!_work_list.is_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3471
a61af66fc99e Initial load
duke
parents:
diff changeset
3472 void RegisterVerifier::process_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3473 TRACE_LINEAR_SCAN(2, tty->cr(); tty->print_cr("process_block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3474
a61af66fc99e Initial load
duke
parents:
diff changeset
3475 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3476 IntervalList* input_state = copy(state_for_block(block));
a61af66fc99e Initial load
duke
parents:
diff changeset
3477
a61af66fc99e Initial load
duke
parents:
diff changeset
3478 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3479 tty->print_cr("Input-State of intervals:");
a61af66fc99e Initial load
duke
parents:
diff changeset
3480 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
3481 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3482 if (input_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3483 tty->print(" %4d", input_state->at(i)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3484 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3485 tty->print(" __");
a61af66fc99e Initial load
duke
parents:
diff changeset
3486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3488 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3489 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3491
a61af66fc99e Initial load
duke
parents:
diff changeset
3492 // process all operations of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3493 process_operations(block->lir(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3494
a61af66fc99e Initial load
duke
parents:
diff changeset
3495 // iterate all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
3496 for (int i = 0; i < block->number_of_sux(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3497 process_successor(block->sux_at(i), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3499 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3500
a61af66fc99e Initial load
duke
parents:
diff changeset
3501 void RegisterVerifier::process_xhandler(XHandler* xhandler, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3502 TRACE_LINEAR_SCAN(2, tty->print_cr("process_xhandler B%d", xhandler->entry_block()->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3503
a61af66fc99e Initial load
duke
parents:
diff changeset
3504 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3505 input_state = copy(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3506
a61af66fc99e Initial load
duke
parents:
diff changeset
3507 if (xhandler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3508 process_operations(xhandler->entry_code(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3510 process_successor(xhandler->entry_block(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3511 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3512
a61af66fc99e Initial load
duke
parents:
diff changeset
3513 void RegisterVerifier::process_successor(BlockBegin* block, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3514 IntervalList* saved_state = state_for_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3515
a61af66fc99e Initial load
duke
parents:
diff changeset
3516 if (saved_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3517 // this block was already processed before.
a61af66fc99e Initial load
duke
parents:
diff changeset
3518 // check if new input_state is consistent with saved_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3519
a61af66fc99e Initial load
duke
parents:
diff changeset
3520 bool saved_state_correct = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3521 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3522 if (input_state->at(i) != saved_state->at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3523 // current input_state and previous saved_state assume a different
a61af66fc99e Initial load
duke
parents:
diff changeset
3524 // interval in this register -> assume that this register is invalid
a61af66fc99e Initial load
duke
parents:
diff changeset
3525 if (saved_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3526 // invalidate old calculation only if it assumed that
a61af66fc99e Initial load
duke
parents:
diff changeset
3527 // register was valid. when the register was already invalid,
a61af66fc99e Initial load
duke
parents:
diff changeset
3528 // then the old calculation was correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
3529 saved_state_correct = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3530 saved_state->at_put(i, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3531
a61af66fc99e Initial load
duke
parents:
diff changeset
3532 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
3533 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3535 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3536
a61af66fc99e Initial load
duke
parents:
diff changeset
3537 if (saved_state_correct) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3538 // already processed block with correct input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3539 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
3540 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3541 // must re-visit this block
a61af66fc99e Initial load
duke
parents:
diff changeset
3542 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
3543 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3545
a61af66fc99e Initial load
duke
parents:
diff changeset
3546 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3547 // block was not processed before, so set initial input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3548 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: initial visit", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3549
a61af66fc99e Initial load
duke
parents:
diff changeset
3550 set_state_for_block(block, copy(input_state));
a61af66fc99e Initial load
duke
parents:
diff changeset
3551 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3553 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3554
a61af66fc99e Initial load
duke
parents:
diff changeset
3555
a61af66fc99e Initial load
duke
parents:
diff changeset
3556 IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3557 IntervalList* copy_state = new IntervalList(input_state->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
3558 copy_state->push_all(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3559 return copy_state;
a61af66fc99e Initial load
duke
parents:
diff changeset
3560 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3561
a61af66fc99e Initial load
duke
parents:
diff changeset
3562 void RegisterVerifier::state_put(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3563 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3564 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3565 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = %d", reg, interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3566 } else if (input_state->at(reg) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3567 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = NULL", reg));
a61af66fc99e Initial load
duke
parents:
diff changeset
3568 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3569
a61af66fc99e Initial load
duke
parents:
diff changeset
3570 input_state->at_put(reg, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3571 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3573
a61af66fc99e Initial load
duke
parents:
diff changeset
3574 bool RegisterVerifier::check_state(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3575 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3576 if (input_state->at(reg) != interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3577 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
3578 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3579 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3581 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3582 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3583
a61af66fc99e Initial load
duke
parents:
diff changeset
3584 void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3585 // visit all instructions of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3586 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3587 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3588
a61af66fc99e Initial load
duke
parents:
diff changeset
3589 for (int i = 0; i < ops->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3590 LIR_Op* op = ops->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3591 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3592
a61af66fc99e Initial load
duke
parents:
diff changeset
3593 TRACE_LINEAR_SCAN(4, op->print_on(tty));
a61af66fc99e Initial load
duke
parents:
diff changeset
3594
a61af66fc99e Initial load
duke
parents:
diff changeset
3595 // check if input operands are correct
a61af66fc99e Initial load
duke
parents:
diff changeset
3596 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3597 int n = visitor.opr_count(LIR_OpVisitState::inputMode);
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::inputMode, 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::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3605
a61af66fc99e Initial load
duke
parents:
diff changeset
3606 has_error |= check_state(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3607 has_error |= check_state(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3608
a61af66fc99e Initial load
duke
parents:
diff changeset
3609 // When an operand is marked with is_last_use, then the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
3610 // removes the register from the fpu stack -> the register contains no value
a61af66fc99e Initial load
duke
parents:
diff changeset
3611 if (opr->is_last_use()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3612 state_put(input_state, interval->assigned_reg(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3613 state_put(input_state, interval->assigned_regHi(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3614 }
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 // invalidate all caller save registers at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
3619 if (visitor.has_call()) {
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
3620 for (j = 0; j < FrameMap::nof_caller_save_cpu_regs(); j++) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3621 state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3623 for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3624 state_put(input_state, reg_num(FrameMap::caller_save_fpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3625 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3626
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
3627 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3628 for (j = 0; j < FrameMap::nof_caller_save_xmm_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3629 state_put(input_state, reg_num(FrameMap::caller_save_xmm_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3631 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3632 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3633
a61af66fc99e Initial load
duke
parents:
diff changeset
3634 // process xhandler before output and temp operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3635 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
3636 n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
3637 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3638 process_xhandler(xhandlers->handler_at(k), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3640
a61af66fc99e Initial load
duke
parents:
diff changeset
3641 // 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
3642 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3643 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3644 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3645 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3646 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3647 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3648 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3650
a61af66fc99e Initial load
duke
parents:
diff changeset
3651 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3652 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3653 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3655
a61af66fc99e Initial load
duke
parents:
diff changeset
3656 // set output operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3657 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3658 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3659 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3660 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3661 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3662 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3663 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3664 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3665
a61af66fc99e Initial load
duke
parents:
diff changeset
3666 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3667 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3668 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3669 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3671 assert(has_error == false, "Error in register allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3672 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3673
a61af66fc99e Initial load
duke
parents:
diff changeset
3674 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3675
a61af66fc99e Initial load
duke
parents:
diff changeset
3676
a61af66fc99e Initial load
duke
parents:
diff changeset
3677
a61af66fc99e Initial load
duke
parents:
diff changeset
3678 // **** Implementation of MoveResolver ******************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3679
a61af66fc99e Initial load
duke
parents:
diff changeset
3680 MoveResolver::MoveResolver(LinearScan* allocator) :
a61af66fc99e Initial load
duke
parents:
diff changeset
3681 _allocator(allocator),
a61af66fc99e Initial load
duke
parents:
diff changeset
3682 _multiple_reads_allowed(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
3683 _mapping_from(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3684 _mapping_from_opr(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3685 _mapping_to(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3686 _insert_list(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
3687 _insert_idx(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
3688 _insertion_buffer()
a61af66fc99e Initial load
duke
parents:
diff changeset
3689 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3690 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3691 _register_blocked[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3693 DEBUG_ONLY(check_empty());
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 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3698
a61af66fc99e Initial load
duke
parents:
diff changeset
3699 void MoveResolver::check_empty() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3700 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
3701 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3702 assert(register_blocked(i) == 0, "register map must be empty before and after processing");
a61af66fc99e Initial load
duke
parents:
diff changeset
3703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3704 assert(_multiple_reads_allowed == false, "must have default value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3705 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3706
a61af66fc99e Initial load
duke
parents:
diff changeset
3707 void MoveResolver::verify_before_resolve() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3708 assert(_mapping_from.length() == _mapping_from_opr.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3709 assert(_mapping_from.length() == _mapping_to.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3710 assert(_insert_list != NULL && _insert_idx != -1, "insert position not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
3711
a61af66fc99e Initial load
duke
parents:
diff changeset
3712 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3713 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3714 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3715 for (j = i + 1; j < _mapping_from.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3716 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
3717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3719 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3720
a61af66fc99e Initial load
duke
parents:
diff changeset
3721 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3722 for (j = i + 1; j < _mapping_to.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3723 assert(_mapping_to.at(i) != _mapping_to.at(j), "cannot write to same interval twice");
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
a61af66fc99e Initial load
duke
parents:
diff changeset
3728 BitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
3729 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3730 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3731 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3732 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3733 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3734 assert(!used_regs.at(it->assigned_reg()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3735 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3736
a61af66fc99e Initial load
duke
parents:
diff changeset
3737 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3738 assert(!used_regs.at(it->assigned_regHi()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3739 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3740 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3741 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3742 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3743 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3744
a61af66fc99e Initial load
duke
parents:
diff changeset
3745 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3746 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3747 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3748 assert(!used_regs.at(it->assigned_reg()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3749 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3750
a61af66fc99e Initial load
duke
parents:
diff changeset
3751 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3752 assert(!used_regs.at(it->assigned_regHi()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3753 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3754 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3755 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3756
a61af66fc99e Initial load
duke
parents:
diff changeset
3757 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3758 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3759 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3760 if (it != NULL && it->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3761 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3762 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3763 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3764 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3765 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3766 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
3767 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3768 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3769
a61af66fc99e Initial load
duke
parents:
diff changeset
3770 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3771
a61af66fc99e Initial load
duke
parents:
diff changeset
3772
a61af66fc99e Initial load
duke
parents:
diff changeset
3773 // mark assigned_reg and assigned_regHi of the interval as blocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3774 void MoveResolver::block_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3775 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3776 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3777 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3778 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3779 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3780 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3781 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3782 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3783 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3784 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3785 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3786
a61af66fc99e Initial load
duke
parents:
diff changeset
3787 // mark assigned_reg and assigned_regHi of the interval as unblocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3788 void MoveResolver::unblock_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3789 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3790 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3791 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3792 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3793 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3794 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3795 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3796 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3797 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3799 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3800
a61af66fc99e Initial load
duke
parents:
diff changeset
3801 // 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
3802 bool MoveResolver::save_to_process_move(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3803 int from_reg = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3804 int from_regHi = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3805 if (from != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3806 from_reg = from->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3807 from_regHi = from->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3808 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3809
a61af66fc99e Initial load
duke
parents:
diff changeset
3810 int reg = to->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3811 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3812 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3813 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3816 reg = to->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3817 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3818 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3819 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3821 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3822
a61af66fc99e Initial load
duke
parents:
diff changeset
3823 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3824 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3825
a61af66fc99e Initial load
duke
parents:
diff changeset
3826
a61af66fc99e Initial load
duke
parents:
diff changeset
3827 void MoveResolver::create_insertion_buffer(LIR_List* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3828 assert(!_insertion_buffer.initialized(), "overwriting existing buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3829 _insertion_buffer.init(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3830 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3831
a61af66fc99e Initial load
duke
parents:
diff changeset
3832 void MoveResolver::append_insertion_buffer() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3833 if (_insertion_buffer.initialized()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3834 _insertion_buffer.lir_list()->append(&_insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
3835 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3836 assert(!_insertion_buffer.initialized(), "must be uninitialized now");
a61af66fc99e Initial load
duke
parents:
diff changeset
3837
a61af66fc99e Initial load
duke
parents:
diff changeset
3838 _insert_list = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
3839 _insert_idx = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3840 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3841
a61af66fc99e Initial load
duke
parents:
diff changeset
3842 void MoveResolver::insert_move(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3843 assert(from_interval->reg_num() != to_interval->reg_num(), "from and to interval equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3844 assert(from_interval->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3845 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3846 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3847
a61af66fc99e Initial load
duke
parents:
diff changeset
3848 LIR_Opr from_opr = LIR_OprFact::virtual_register(from_interval->reg_num(), from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3849 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3850
a61af66fc99e Initial load
duke
parents:
diff changeset
3851 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3852 // the last_use flag is an optimization for FPU stack allocation. When the same
a61af66fc99e Initial load
duke
parents:
diff changeset
3853 // input interval is used in more than one move, then it is too difficult to determine
a61af66fc99e Initial load
duke
parents:
diff changeset
3854 // if this move is really the last use.
a61af66fc99e Initial load
duke
parents:
diff changeset
3855 from_opr = from_opr->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
3856 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3857 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3858
a61af66fc99e Initial load
duke
parents:
diff changeset
3859 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
3860 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3861
a61af66fc99e Initial load
duke
parents:
diff changeset
3862 void MoveResolver::insert_move(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3863 assert(from_opr->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3864 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3865 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3866
a61af66fc99e Initial load
duke
parents:
diff changeset
3867 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3868 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3869
a61af66fc99e Initial load
duke
parents:
diff changeset
3870 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
3871 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3872
a61af66fc99e Initial load
duke
parents:
diff changeset
3873
a61af66fc99e Initial load
duke
parents:
diff changeset
3874 void MoveResolver::resolve_mappings() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3875 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
3876 DEBUG_ONLY(verify_before_resolve());
a61af66fc99e Initial load
duke
parents:
diff changeset
3877
a61af66fc99e Initial load
duke
parents:
diff changeset
3878 // Block all registers that are used as input operands of a move.
a61af66fc99e Initial load
duke
parents:
diff changeset
3879 // When a register is blocked, no move to this register is emitted.
a61af66fc99e Initial load
duke
parents:
diff changeset
3880 // This is necessary for detecting cycles in moves.
a61af66fc99e Initial load
duke
parents:
diff changeset
3881 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3882 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3883 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3884 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3885 block_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3887 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3888
a61af66fc99e Initial load
duke
parents:
diff changeset
3889 int spill_candidate = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3890 while (_mapping_from.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3891 bool processed_interval = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3892
a61af66fc99e Initial load
duke
parents:
diff changeset
3893 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3894 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3895 Interval* to_interval = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3896
a61af66fc99e Initial load
duke
parents:
diff changeset
3897 if (save_to_process_move(from_interval, to_interval)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3898 // this inverval can be processed because target is free
a61af66fc99e Initial load
duke
parents:
diff changeset
3899 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3900 insert_move(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3901 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3902 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3903 insert_move(_mapping_from_opr.at(i), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3904 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3905 _mapping_from.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3906 _mapping_from_opr.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3907 _mapping_to.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3908
a61af66fc99e Initial load
duke
parents:
diff changeset
3909 processed_interval = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3910 } else if (from_interval != NULL && from_interval->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3911 // this interval cannot be processed now because target is not free
a61af66fc99e Initial load
duke
parents:
diff changeset
3912 // it starts in a register, so it is a possible candidate for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
3913 spill_candidate = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3914 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3915 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3916
a61af66fc99e Initial load
duke
parents:
diff changeset
3917 if (!processed_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3918 // no move could be processed because there is a cycle in the move list
a61af66fc99e Initial load
duke
parents:
diff changeset
3919 // (e.g. r1 -> r2, r2 -> r1), so one interval must be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
3920 assert(spill_candidate != -1, "no interval in register for spilling found");
a61af66fc99e Initial load
duke
parents:
diff changeset
3921
a61af66fc99e Initial load
duke
parents:
diff changeset
3922 // create a new spill interval and assign a stack slot to it
a61af66fc99e Initial load
duke
parents:
diff changeset
3923 Interval* from_interval = _mapping_from.at(spill_candidate);
a61af66fc99e Initial load
duke
parents:
diff changeset
3924 Interval* spill_interval = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3925 spill_interval->set_type(from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3926
a61af66fc99e Initial load
duke
parents:
diff changeset
3927 // add a dummy range because real position is difficult to calculate
a61af66fc99e Initial load
duke
parents:
diff changeset
3928 // Note: this range is a special case when the integrity of the allocation is checked
a61af66fc99e Initial load
duke
parents:
diff changeset
3929 spill_interval->add_range(1, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3930
a61af66fc99e Initial load
duke
parents:
diff changeset
3931 // do not allocate a new spill slot for temporary interval, but
a61af66fc99e Initial load
duke
parents:
diff changeset
3932 // use spill slot assigned to from_interval. Otherwise moves from
a61af66fc99e Initial load
duke
parents:
diff changeset
3933 // one stack slot to another can happen (not allowed by LIR_Assembler
a61af66fc99e Initial load
duke
parents:
diff changeset
3934 int spill_slot = from_interval->canonical_spill_slot();
a61af66fc99e Initial load
duke
parents:
diff changeset
3935 if (spill_slot < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3936 spill_slot = allocator()->allocate_spill_slot(type2spill_size[spill_interval->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3937 from_interval->set_canonical_spill_slot(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3939 spill_interval->assign_reg(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3940 allocator()->append_interval(spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3941
a61af66fc99e Initial load
duke
parents:
diff changeset
3942 TRACE_LINEAR_SCAN(4, tty->print_cr("created new Interval %d for spilling", spill_interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3943
a61af66fc99e Initial load
duke
parents:
diff changeset
3944 // insert a move from register to stack and update the mapping
a61af66fc99e Initial load
duke
parents:
diff changeset
3945 insert_move(from_interval, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3946 _mapping_from.at_put(spill_candidate, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3947 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3948 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3949 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3950
a61af66fc99e Initial load
duke
parents:
diff changeset
3951 // reset to default value
a61af66fc99e Initial load
duke
parents:
diff changeset
3952 _multiple_reads_allowed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3953
a61af66fc99e Initial load
duke
parents:
diff changeset
3954 // check that all intervals have been processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3955 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3956 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3957
a61af66fc99e Initial load
duke
parents:
diff changeset
3958
a61af66fc99e Initial load
duke
parents:
diff changeset
3959 void MoveResolver::set_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3960 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
3961 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
3962
a61af66fc99e Initial load
duke
parents:
diff changeset
3963 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3964 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3965 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3967
a61af66fc99e Initial load
duke
parents:
diff changeset
3968 void MoveResolver::move_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3969 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
3970
a61af66fc99e Initial load
duke
parents:
diff changeset
3971 if (_insert_list != NULL && (insert_list != _insert_list || insert_idx != _insert_idx)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3972 // insert position changed -> resolve current mappings
a61af66fc99e Initial load
duke
parents:
diff changeset
3973 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3974 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3975
a61af66fc99e Initial load
duke
parents:
diff changeset
3976 if (insert_list != _insert_list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3977 // block changed -> append insertion_buffer because it is
a61af66fc99e Initial load
duke
parents:
diff changeset
3978 // bound to a specific block and create a new insertion_buffer
a61af66fc99e Initial load
duke
parents:
diff changeset
3979 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
3980 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3981 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3982
a61af66fc99e Initial load
duke
parents:
diff changeset
3983 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3984 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3985 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3986
a61af66fc99e Initial load
duke
parents:
diff changeset
3987 void MoveResolver::add_mapping(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3988 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
3989
a61af66fc99e Initial load
duke
parents:
diff changeset
3990 _mapping_from.append(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3991 _mapping_from_opr.append(LIR_OprFact::illegalOpr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3992 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3993 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3994
a61af66fc99e Initial load
duke
parents:
diff changeset
3995
a61af66fc99e Initial load
duke
parents:
diff changeset
3996 void MoveResolver::add_mapping(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3997 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
3998 assert(from_opr->is_constant(), "only for constants");
a61af66fc99e Initial load
duke
parents:
diff changeset
3999
a61af66fc99e Initial load
duke
parents:
diff changeset
4000 _mapping_from.append(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
4001 _mapping_from_opr.append(from_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
4002 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4004
a61af66fc99e Initial load
duke
parents:
diff changeset
4005 void MoveResolver::resolve_and_append_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4006 if (has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4007 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
4008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4009 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
4010 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4011
a61af66fc99e Initial load
duke
parents:
diff changeset
4012
a61af66fc99e Initial load
duke
parents:
diff changeset
4013
a61af66fc99e Initial load
duke
parents:
diff changeset
4014 // **** Implementation of Range *************************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4015
a61af66fc99e Initial load
duke
parents:
diff changeset
4016 Range::Range(int from, int to, Range* next) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4017 _from(from),
a61af66fc99e Initial load
duke
parents:
diff changeset
4018 _to(to),
a61af66fc99e Initial load
duke
parents:
diff changeset
4019 _next(next)
a61af66fc99e Initial load
duke
parents:
diff changeset
4020 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4021 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4022
a61af66fc99e Initial load
duke
parents:
diff changeset
4023 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4024 Range* Range::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4025 void Range::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4026 _end = new (arena) Range(max_jint, max_jint, NULL);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4028
a61af66fc99e Initial load
duke
parents:
diff changeset
4029 int Range::intersects_at(Range* r2) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4030 const Range* r1 = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4031
a61af66fc99e Initial load
duke
parents:
diff changeset
4032 assert(r1 != NULL && r2 != NULL, "null ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
4033 assert(r1 != _end && r2 != _end, "empty ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
4034
a61af66fc99e Initial load
duke
parents:
diff changeset
4035 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
4036 if (r1->from() < r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4037 if (r1->to() <= r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4038 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4039 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4040 return r2->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4041 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4042 } else if (r2->from() < r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4043 if (r2->to() <= r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4044 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4045 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4046 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4047 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4048 } else { // r1->from() == r2->from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4049 if (r1->from() == r1->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4050 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4051 } else if (r2->from() == r2->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4052 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4053 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4054 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4055 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4056 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4057 } while (true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4058 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4059
a61af66fc99e Initial load
duke
parents:
diff changeset
4060 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4061 void Range::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4062 out->print("[%d, %d[ ", _from, _to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4064 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4065
a61af66fc99e Initial load
duke
parents:
diff changeset
4066
a61af66fc99e Initial load
duke
parents:
diff changeset
4067
a61af66fc99e Initial load
duke
parents:
diff changeset
4068 // **** Implementation of Interval **********************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4069
a61af66fc99e Initial load
duke
parents:
diff changeset
4070 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4071 Interval* Interval::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4072 void Interval::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4073 Range::initialize(arena);
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4074 _end = new (arena) Interval(-1);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4075 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4076
a61af66fc99e Initial load
duke
parents:
diff changeset
4077 Interval::Interval(int reg_num) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4078 _reg_num(reg_num),
a61af66fc99e Initial load
duke
parents:
diff changeset
4079 _type(T_ILLEGAL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4080 _first(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4081 _use_pos_and_kinds(12),
a61af66fc99e Initial load
duke
parents:
diff changeset
4082 _current(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4083 _next(_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
4084 _state(invalidState),
a61af66fc99e Initial load
duke
parents:
diff changeset
4085 _assigned_reg(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4086 _assigned_regHi(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4087 _cached_to(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4088 _cached_opr(LIR_OprFact::illegalOpr),
a61af66fc99e Initial load
duke
parents:
diff changeset
4089 _cached_vm_reg(VMRegImpl::Bad()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4090 _split_children(0),
a61af66fc99e Initial load
duke
parents:
diff changeset
4091 _canonical_spill_slot(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4092 _insert_move_when_activated(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
4093 _register_hint(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4094 _spill_state(noDefinitionFound),
a61af66fc99e Initial load
duke
parents:
diff changeset
4095 _spill_definition_pos(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4096 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4097 _split_parent = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4098 _current_split_child = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4099 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4100
a61af66fc99e Initial load
duke
parents:
diff changeset
4101 int Interval::calc_to() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4102 assert(_first != Range::end(), "interval has no range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4103
a61af66fc99e Initial load
duke
parents:
diff changeset
4104 Range* r = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4105 while (r->next() != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4106 r = r->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4108 return r->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4110
a61af66fc99e Initial load
duke
parents:
diff changeset
4111
a61af66fc99e Initial load
duke
parents:
diff changeset
4112 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4113 // consistency check of split-children
a61af66fc99e Initial load
duke
parents:
diff changeset
4114 void Interval::check_split_children() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4115 if (_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4116 assert(is_split_parent(), "only split parents can have children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4117
a61af66fc99e Initial load
duke
parents:
diff changeset
4118 for (int i = 0; i < _split_children.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4119 Interval* i1 = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4120
a61af66fc99e Initial load
duke
parents:
diff changeset
4121 assert(i1->split_parent() == this, "not a split child of this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4122 assert(i1->type() == type(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4123 assert(i1->canonical_spill_slot() == canonical_spill_slot(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4124
a61af66fc99e Initial load
duke
parents:
diff changeset
4125 for (int j = i + 1; j < _split_children.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4126 Interval* i2 = _split_children.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
4127
a61af66fc99e Initial load
duke
parents:
diff changeset
4128 assert(i1->reg_num() != i2->reg_num(), "same register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
4129
a61af66fc99e Initial load
duke
parents:
diff changeset
4130 if (i1->from() < i2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4131 assert(i1->to() <= i2->from() && i1->to() < i2->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4132 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4133 assert(i2->from() < i1->from(), "intervals start at same op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4134 assert(i2->to() <= i1->from() && i2->to() < i1->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4136 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4137 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4140 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4141
a61af66fc99e Initial load
duke
parents:
diff changeset
4142 Interval* Interval::register_hint(bool search_split_child) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4143 if (!search_split_child) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4144 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4146
a61af66fc99e Initial load
duke
parents:
diff changeset
4147 if (_register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4148 assert(_register_hint->is_split_parent(), "ony split parents are valid hint registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
4149
a61af66fc99e Initial load
duke
parents:
diff changeset
4150 if (_register_hint->assigned_reg() >= 0 && _register_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4151 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4152
a61af66fc99e Initial load
duke
parents:
diff changeset
4153 } else if (_register_hint->_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4154 // search the first split child that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4155 int len = _register_hint->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4156 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4157 Interval* cur = _register_hint->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4158
a61af66fc99e Initial load
duke
parents:
diff changeset
4159 if (cur->assigned_reg() >= 0 && cur->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4160 return cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4165
a61af66fc99e Initial load
duke
parents:
diff changeset
4166 // no hint interval found that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4167 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4168 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4169
a61af66fc99e Initial load
duke
parents:
diff changeset
4170
a61af66fc99e Initial load
duke
parents:
diff changeset
4171 Interval* Interval::split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4172 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4173 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4174
a61af66fc99e Initial load
duke
parents:
diff changeset
4175 Interval* result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4176 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4177 result = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4178 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4179 result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4180 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4181
a61af66fc99e Initial load
duke
parents:
diff changeset
4182 // in outputMode, the end of the interval (op_id == cur->to()) is not valid
a61af66fc99e Initial load
duke
parents:
diff changeset
4183 int to_offset = (mode == LIR_OpVisitState::outputMode ? 0 : 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4184
a61af66fc99e Initial load
duke
parents:
diff changeset
4185 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4186 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4187 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4188 if (cur->from() <= op_id && op_id < cur->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4189 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4190 // exchange current split child to start of list (faster access for next call)
a61af66fc99e Initial load
duke
parents:
diff changeset
4191 _split_children.at_put(i, _split_children.at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
4192 _split_children.at_put(0, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4194
a61af66fc99e Initial load
duke
parents:
diff changeset
4195 // interval found
a61af66fc99e Initial load
duke
parents:
diff changeset
4196 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4197 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
4198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4200
a61af66fc99e Initial load
duke
parents:
diff changeset
4201 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4202 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4203 Interval* tmp = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4204 if (tmp != result && tmp->from() <= op_id && op_id < tmp->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4205 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
4206 result->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4207 tmp->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4208 assert(false, "two valid result intervals found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4210 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4211 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4213
a61af66fc99e Initial load
duke
parents:
diff changeset
4214 assert(result != NULL, "no matching interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4215 assert(result->covers(op_id, mode), "op_id not covered by interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4216
a61af66fc99e Initial load
duke
parents:
diff changeset
4217 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4219
a61af66fc99e Initial load
duke
parents:
diff changeset
4220
a61af66fc99e Initial load
duke
parents:
diff changeset
4221 // returns the last split child that ends before the given op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
4222 Interval* Interval::split_child_before_op_id(int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4223 assert(op_id >= 0, "invalid op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4224
a61af66fc99e Initial load
duke
parents:
diff changeset
4225 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4226 Interval* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4227
a61af66fc99e Initial load
duke
parents:
diff changeset
4228 int len = parent->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4229 assert(len > 0, "no split children available");
a61af66fc99e Initial load
duke
parents:
diff changeset
4230
a61af66fc99e Initial load
duke
parents:
diff changeset
4231 for (int i = len - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4232 Interval* cur = parent->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4233 if (cur->to() <= op_id && (result == NULL || result->to() < cur->to())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4234 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4235 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4237
a61af66fc99e Initial load
duke
parents:
diff changeset
4238 assert(result != NULL, "no split child found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4239 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4241
a61af66fc99e Initial load
duke
parents:
diff changeset
4242
a61af66fc99e Initial load
duke
parents:
diff changeset
4243 // checks if op_id is covered by any split child
a61af66fc99e Initial load
duke
parents:
diff changeset
4244 bool Interval::split_child_covers(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4245 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4246 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4247
a61af66fc99e Initial load
duke
parents:
diff changeset
4248 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4249 // simple case if interval was not split
a61af66fc99e Initial load
duke
parents:
diff changeset
4250 return covers(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
4251
a61af66fc99e Initial load
duke
parents:
diff changeset
4252 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4253 // extended case: check all split children
a61af66fc99e Initial load
duke
parents:
diff changeset
4254 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4255 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4256 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4257 if (cur->covers(op_id, mode)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4258 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4259 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4261 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4264
a61af66fc99e Initial load
duke
parents:
diff changeset
4265
a61af66fc99e Initial load
duke
parents:
diff changeset
4266 // Note: use positions are sorted descending -> first use has highest index
a61af66fc99e Initial load
duke
parents:
diff changeset
4267 int Interval::first_usage(IntervalUseKind min_use_kind) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4268 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4269
a61af66fc99e Initial load
duke
parents:
diff changeset
4270 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4271 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4272 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4275 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4277
a61af66fc99e Initial load
duke
parents:
diff changeset
4278 int Interval::next_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4279 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4280
a61af66fc99e Initial load
duke
parents:
diff changeset
4281 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4282 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
4283 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4284 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4286 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4288
a61af66fc99e Initial load
duke
parents:
diff changeset
4289 int Interval::next_usage_exact(IntervalUseKind exact_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4290 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4291
a61af66fc99e Initial load
duke
parents:
diff changeset
4292 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4293 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
4294 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4297 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4299
a61af66fc99e Initial load
duke
parents:
diff changeset
4300 int Interval::previous_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4301 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4302
a61af66fc99e Initial load
duke
parents:
diff changeset
4303 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4304 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4305 if (_use_pos_and_kinds.at(i) > from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4306 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4308 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4309 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4310 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4312 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4313 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4314
a61af66fc99e Initial load
duke
parents:
diff changeset
4315 void Interval::add_use_pos(int pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4316 assert(covers(pos, LIR_OpVisitState::inputMode), "use position not covered by live range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4317
a61af66fc99e Initial load
duke
parents:
diff changeset
4318 // do not add use positions for precolored intervals because
a61af66fc99e Initial load
duke
parents:
diff changeset
4319 // they are never used
a61af66fc99e Initial load
duke
parents:
diff changeset
4320 if (use_kind != noUse && reg_num() >= LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4321 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4322 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4323 for (int i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4324 assert(pos <= _use_pos_and_kinds.at(i), "already added a use-position with lower position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4325 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
4326 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4327 assert(_use_pos_and_kinds.at(i) < _use_pos_and_kinds.at(i - 2), "not sorted descending");
a61af66fc99e Initial load
duke
parents:
diff changeset
4328 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4329 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4330 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4331
a61af66fc99e Initial load
duke
parents:
diff changeset
4332 // Note: add_use is called in descending order, so list gets sorted
a61af66fc99e Initial load
duke
parents:
diff changeset
4333 // automatically by just appending new use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4334 int len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4335 if (len == 0 || _use_pos_and_kinds.at(len - 2) > pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4336 _use_pos_and_kinds.append(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4337 _use_pos_and_kinds.append(use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4338 } else if (_use_pos_and_kinds.at(len - 1) < use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4339 assert(_use_pos_and_kinds.at(len - 2) == pos, "list not sorted correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
4340 _use_pos_and_kinds.at_put(len - 1, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4343 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4344
a61af66fc99e Initial load
duke
parents:
diff changeset
4345 void Interval::add_range(int from, int to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4346 assert(from < to, "invalid range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4347 assert(first() == Range::end() || to < first()->next()->from(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4348 assert(from <= first()->to(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4349
a61af66fc99e Initial load
duke
parents:
diff changeset
4350 if (first()->from() <= to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4351 // join intersecting ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4352 first()->set_from(MIN2(from, first()->from()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4353 first()->set_to (MAX2(to, first()->to()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4354 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4355 // insert new range
a61af66fc99e Initial load
duke
parents:
diff changeset
4356 _first = new Range(from, to, first());
a61af66fc99e Initial load
duke
parents:
diff changeset
4357 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4359
a61af66fc99e Initial load
duke
parents:
diff changeset
4360 Interval* Interval::new_split_child() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4361 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4362 Interval* result = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4363 result->set_type(type());
a61af66fc99e Initial load
duke
parents:
diff changeset
4364
a61af66fc99e Initial load
duke
parents:
diff changeset
4365 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4366 result->_split_parent = parent;
a61af66fc99e Initial load
duke
parents:
diff changeset
4367 result->set_register_hint(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
4368
a61af66fc99e Initial load
duke
parents:
diff changeset
4369 // insert new interval in children-list of parent
a61af66fc99e Initial load
duke
parents:
diff changeset
4370 if (parent->_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4371 assert(is_split_parent(), "list must be initialized at first split");
a61af66fc99e Initial load
duke
parents:
diff changeset
4372
a61af66fc99e Initial load
duke
parents:
diff changeset
4373 parent->_split_children = IntervalList(4);
a61af66fc99e Initial load
duke
parents:
diff changeset
4374 parent->_split_children.append(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4376 parent->_split_children.append(result);
a61af66fc99e Initial load
duke
parents:
diff changeset
4377
a61af66fc99e Initial load
duke
parents:
diff changeset
4378 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4380
a61af66fc99e Initial load
duke
parents:
diff changeset
4381 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4382 // the remainder as a new interval.
a61af66fc99e Initial load
duke
parents:
diff changeset
4383 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4384 // when an interval is split, a bi-directional link is established between the original interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4385 // (the split parent) and the intervals that are split off this interval (the split children)
a61af66fc99e Initial load
duke
parents:
diff changeset
4386 // When a split child is split again, the new created interval is also a direct child
a61af66fc99e Initial load
duke
parents:
diff changeset
4387 // of the original parent (there is no tree of split children stored, but a flat list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4388 // All split children are spilled to the same stack slot (stored in _canonical_spill_slot)
a61af66fc99e Initial load
duke
parents:
diff changeset
4389 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4390 // Note: The new interval has no valid reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
4391 Interval* Interval::split(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4392 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4393
a61af66fc99e Initial load
duke
parents:
diff changeset
4394 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4395 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4396
a61af66fc99e Initial load
duke
parents:
diff changeset
4397 // split the ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4398 Range* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4399 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4400 while (cur != Range::end() && cur->to() <= split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4401 prev = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4402 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4403 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4404 assert(cur != Range::end(), "split interval after end of last range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4405
a61af66fc99e Initial load
duke
parents:
diff changeset
4406 if (cur->from() < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4407 result->_first = new Range(split_pos, cur->to(), cur->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
4408 cur->set_to(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4409 cur->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4410
a61af66fc99e Initial load
duke
parents:
diff changeset
4411 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4412 assert(prev != NULL, "split before start of first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4413 result->_first = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4414 prev->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4415 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4416 result->_current = result->_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4417 _cached_to = -1; // clear cached value
a61af66fc99e Initial load
duke
parents:
diff changeset
4418
a61af66fc99e Initial load
duke
parents:
diff changeset
4419 // split list of use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4420 int total_len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4421 int start_idx = total_len - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4422 while (start_idx >= 0 && _use_pos_and_kinds.at(start_idx) < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4423 start_idx -= 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4424 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4425
a61af66fc99e Initial load
duke
parents:
diff changeset
4426 intStack new_use_pos_and_kinds(total_len - start_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
4427 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4428 for (i = start_idx + 2; i < total_len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4429 new_use_pos_and_kinds.append(_use_pos_and_kinds.at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
4430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4431
a61af66fc99e Initial load
duke
parents:
diff changeset
4432 _use_pos_and_kinds.truncate(start_idx + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4433 result->_use_pos_and_kinds = _use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4434 _use_pos_and_kinds = new_use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4435
a61af66fc99e Initial load
duke
parents:
diff changeset
4436 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4437 assert(_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4438 assert(result->_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4439 assert(_use_pos_and_kinds.length() + result->_use_pos_and_kinds.length() == total_len, "missed some entries");
a61af66fc99e Initial load
duke
parents:
diff changeset
4440
a61af66fc99e Initial load
duke
parents:
diff changeset
4441 for (i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4442 assert(_use_pos_and_kinds.at(i) < split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4443 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
4444 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4445 for (i = 0; i < result->_use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4446 assert(result->_use_pos_and_kinds.at(i) >= split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4447 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
4448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4449 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4450
a61af66fc99e Initial load
duke
parents:
diff changeset
4451 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4452 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4453
a61af66fc99e Initial load
duke
parents:
diff changeset
4454 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4455 // the head as a new interval (the original interval is the tail)
a61af66fc99e Initial load
duke
parents:
diff changeset
4456 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4457 // Currently, only the first range can be split, and the new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4458 // must not have split positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4459 Interval* Interval::split_from_start(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4460 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4461 assert(split_pos > from() && split_pos < to(), "can only split inside interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4462 assert(split_pos > _first->from() && split_pos <= _first->to(), "can only split inside first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4463 assert(first_usage(noUse) > split_pos, "can not split when use positions are present");
a61af66fc99e Initial load
duke
parents:
diff changeset
4464
a61af66fc99e Initial load
duke
parents:
diff changeset
4465 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4466 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4467
a61af66fc99e Initial load
duke
parents:
diff changeset
4468 // the new created interval has only one range (checked by assertion above),
a61af66fc99e Initial load
duke
parents:
diff changeset
4469 // so the splitting of the ranges is very simple
a61af66fc99e Initial load
duke
parents:
diff changeset
4470 result->add_range(_first->from(), split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4471
a61af66fc99e Initial load
duke
parents:
diff changeset
4472 if (split_pos == _first->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4473 assert(_first->next() != Range::end(), "must not be at end");
a61af66fc99e Initial load
duke
parents:
diff changeset
4474 _first = _first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4475 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4476 _first->set_from(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4477 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4478
a61af66fc99e Initial load
duke
parents:
diff changeset
4479 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4481
a61af66fc99e Initial load
duke
parents:
diff changeset
4482
a61af66fc99e Initial load
duke
parents:
diff changeset
4483 // returns true if the op_id is inside the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4484 bool Interval::covers(int op_id, LIR_OpVisitState::OprMode mode) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4485 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4486
a61af66fc99e Initial load
duke
parents:
diff changeset
4487 while (cur != Range::end() && cur->to() < op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4488 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4490 if (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4491 assert(cur->to() != cur->next()->from(), "ranges not separated");
a61af66fc99e Initial load
duke
parents:
diff changeset
4492
a61af66fc99e Initial load
duke
parents:
diff changeset
4493 if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4494 return cur->from() <= op_id && op_id < cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4495 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4496 return cur->from() <= op_id && op_id <= cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4499 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4501
a61af66fc99e Initial load
duke
parents:
diff changeset
4502 // returns true if the interval has any hole between hole_from and hole_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4503 // (even if the hole has only the length 1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4504 bool Interval::has_hole_between(int hole_from, int hole_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4505 assert(hole_from < hole_to, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4506 assert(from() <= hole_from && hole_to <= to(), "index out of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4507
a61af66fc99e Initial load
duke
parents:
diff changeset
4508 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4509 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4510 assert(cur->to() < cur->next()->from(), "no space between ranges");
a61af66fc99e Initial load
duke
parents:
diff changeset
4511
a61af66fc99e Initial load
duke
parents:
diff changeset
4512 // hole-range starts before this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4513 if (hole_from < cur->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4514 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4515
a61af66fc99e Initial load
duke
parents:
diff changeset
4516 // hole-range completely inside this range -> no hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4517 } else if (hole_to <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4518 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4519
a61af66fc99e Initial load
duke
parents:
diff changeset
4520 // overlapping of hole-range with this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4521 } else if (hole_from <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4522 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4523 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4524
a61af66fc99e Initial load
duke
parents:
diff changeset
4525 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4526 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4527
a61af66fc99e Initial load
duke
parents:
diff changeset
4528 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4529 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4530
a61af66fc99e Initial load
duke
parents:
diff changeset
4531
a61af66fc99e Initial load
duke
parents:
diff changeset
4532 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4533 void Interval::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4534 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
4535 const char* UseKind2Name[] = { "N", "L", "S", "M" };
a61af66fc99e Initial load
duke
parents:
diff changeset
4536
a61af66fc99e Initial load
duke
parents:
diff changeset
4537 const char* type_name;
a61af66fc99e Initial load
duke
parents:
diff changeset
4538 LIR_Opr opr = LIR_OprFact::illegal();
a61af66fc99e Initial load
duke
parents:
diff changeset
4539 if (reg_num() < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4540 type_name = "fixed";
a61af66fc99e Initial load
duke
parents:
diff changeset
4541 // need a temporary operand for fixed intervals because type() cannot be called
a61af66fc99e Initial load
duke
parents:
diff changeset
4542 if (assigned_reg() >= pd_first_cpu_reg && assigned_reg() <= pd_last_cpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4543 opr = LIR_OprFact::single_cpu(assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4544 } else if (assigned_reg() >= pd_first_fpu_reg && assigned_reg() <= pd_last_fpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4545 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
4546 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4547 } else if (assigned_reg() >= pd_first_xmm_reg && assigned_reg() <= pd_last_xmm_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4548 opr = LIR_OprFact::single_xmm(assigned_reg() - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
4549 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4550 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4551 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
4552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4553 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4554 type_name = type2name(type());
2081
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
4555 if (assigned_reg() != -1 &&
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
4556 (LinearScan::num_physical_regs(type()) == 1 || assigned_regHi() != -1)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4557 opr = LinearScan::calc_operand_for_interval(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4560
a61af66fc99e Initial load
duke
parents:
diff changeset
4561 out->print("%d %s ", reg_num(), type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
4562 if (opr->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4563 out->print("\"");
a61af66fc99e Initial load
duke
parents:
diff changeset
4564 opr->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4565 out->print("\" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
4566 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4567 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
4568
a61af66fc99e Initial load
duke
parents:
diff changeset
4569 // print ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4570 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4571 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4572 cur->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4573 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4574 assert(cur != NULL, "range list not closed with range sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
4575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4576
a61af66fc99e Initial load
duke
parents:
diff changeset
4577 // print use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4578 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4579 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4580 for (int i =_use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4581 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
4582 assert(prev < _use_pos_and_kinds.at(i), "use positions not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
4583
a61af66fc99e Initial load
duke
parents:
diff changeset
4584 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
4585 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4586 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4587
a61af66fc99e Initial load
duke
parents:
diff changeset
4588 out->print(" \"%s\"", SpillState2Name[spill_state()]);
a61af66fc99e Initial load
duke
parents:
diff changeset
4589 out->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4590 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4591 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4592
a61af66fc99e Initial load
duke
parents:
diff changeset
4593
a61af66fc99e Initial load
duke
parents:
diff changeset
4594
a61af66fc99e Initial load
duke
parents:
diff changeset
4595 // **** Implementation of IntervalWalker ****************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4596
a61af66fc99e Initial load
duke
parents:
diff changeset
4597 IntervalWalker::IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4598 : _compilation(allocator->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
4599 , _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4600 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4601 _unhandled_first[fixedKind] = unhandled_fixed_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4602 _unhandled_first[anyKind] = unhandled_any_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4603 _active_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4604 _inactive_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4605 _active_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4606 _inactive_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4607 _current_position = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4608 _current = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4609 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4611
a61af66fc99e Initial load
duke
parents:
diff changeset
4612
a61af66fc99e Initial load
duke
parents:
diff changeset
4613 // append interval at top of list
a61af66fc99e Initial load
duke
parents:
diff changeset
4614 void IntervalWalker::append_unsorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4615 interval->set_next(*list); *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4616 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4617
a61af66fc99e Initial load
duke
parents:
diff changeset
4618
a61af66fc99e Initial load
duke
parents:
diff changeset
4619 // append interval in order of current range from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4620 void IntervalWalker::append_sorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4621 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4622 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4623 while (cur->current_from() < interval->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4624 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4625 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4626 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4627 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4628 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4629 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4631 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4632 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4633
a61af66fc99e Initial load
duke
parents:
diff changeset
4634 void IntervalWalker::append_to_unhandled(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4635 assert(interval->from() >= current()->current_from(), "cannot append new interval before current walk position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4636
a61af66fc99e Initial load
duke
parents:
diff changeset
4637 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4638 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4639 while (cur->from() < interval->from() || (cur->from() == interval->from() && cur->first_usage(noUse) < interval->first_usage(noUse))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4640 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4642 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4643 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4644 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4645 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4647 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4649
a61af66fc99e Initial load
duke
parents:
diff changeset
4650
a61af66fc99e Initial load
duke
parents:
diff changeset
4651 inline bool IntervalWalker::remove_from_list(Interval** list, Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4652 while (*list != Interval::end() && *list != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4653 list = (*list)->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4655 if (*list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4656 assert(*list == i, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4657 *list = (*list)->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4658 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4659 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4660 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4661 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4662 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4663
a61af66fc99e Initial load
duke
parents:
diff changeset
4664 void IntervalWalker::remove_from_list(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4665 bool deleted;
a61af66fc99e Initial load
duke
parents:
diff changeset
4666
a61af66fc99e Initial load
duke
parents:
diff changeset
4667 if (i->state() == activeState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4668 deleted = remove_from_list(active_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4669 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4670 assert(i->state() == inactiveState, "invalid state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4671 deleted = remove_from_list(inactive_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4672 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4673
a61af66fc99e Initial load
duke
parents:
diff changeset
4674 assert(deleted, "interval has not been found in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
4675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4676
a61af66fc99e Initial load
duke
parents:
diff changeset
4677
a61af66fc99e Initial load
duke
parents:
diff changeset
4678 void IntervalWalker::walk_to(IntervalState state, int from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4679 assert (state == activeState || state == inactiveState, "wrong state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4680 for_each_interval_kind(kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4681 Interval** prev = state == activeState ? active_first_addr(kind) : inactive_first_addr(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4682 Interval* next = *prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4683 while (next->current_from() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4684 Interval* cur = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4685 next = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4686
a61af66fc99e Initial load
duke
parents:
diff changeset
4687 bool range_has_changed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4688 while (cur->current_to() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4689 cur->next_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4690 range_has_changed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4691 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4692
a61af66fc99e Initial load
duke
parents:
diff changeset
4693 // also handle move from inactive list to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4694 range_has_changed = range_has_changed || (state == inactiveState && cur->current_from() <= from);
a61af66fc99e Initial load
duke
parents:
diff changeset
4695
a61af66fc99e Initial load
duke
parents:
diff changeset
4696 if (range_has_changed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4697 // remove cur from list
a61af66fc99e Initial load
duke
parents:
diff changeset
4698 *prev = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4699 if (cur->current_at_end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4700 // move to handled state (not maintained as a list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4701 cur->set_state(handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4702 interval_moved(cur, kind, state, handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4703 } else if (cur->current_from() <= from){
a61af66fc99e Initial load
duke
parents:
diff changeset
4704 // sort into active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4705 append_sorted(active_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4706 cur->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4707 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4708 assert(state == activeState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4709 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4710 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4711 interval_moved(cur, kind, state, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4712 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4713 // sort into inactive list
a61af66fc99e Initial load
duke
parents:
diff changeset
4714 append_sorted(inactive_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4715 cur->set_state(inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4716 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4717 assert(state == inactiveState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4718 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4719 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4720 interval_moved(cur, kind, state, inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4722 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4723 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4724 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
4725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4726 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4728 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4729
a61af66fc99e Initial load
duke
parents:
diff changeset
4730
a61af66fc99e Initial load
duke
parents:
diff changeset
4731 void IntervalWalker::next_interval() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4732 IntervalKind kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4733 Interval* any = _unhandled_first[anyKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4734 Interval* fixed = _unhandled_first[fixedKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4735
a61af66fc99e Initial load
duke
parents:
diff changeset
4736 if (any != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4737 // intervals may start at same position -> prefer fixed interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4738 kind = fixed != Interval::end() && fixed->from() <= any->from() ? fixedKind : anyKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4739
a61af66fc99e Initial load
duke
parents:
diff changeset
4740 assert (kind == fixedKind && fixed->from() <= any->from() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
4741 kind == anyKind && any->from() <= fixed->from(), "wrong interval!!!");
a61af66fc99e Initial load
duke
parents:
diff changeset
4742 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
4743
a61af66fc99e Initial load
duke
parents:
diff changeset
4744 } else if (fixed != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4745 kind = fixedKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4746 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4747 _current = NULL; return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4749 _current_kind = kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4750 _current = _unhandled_first[kind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4751 _unhandled_first[kind] = _current->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4752 _current->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4753 _current->rewind_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4754 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4755
a61af66fc99e Initial load
duke
parents:
diff changeset
4756
a61af66fc99e Initial load
duke
parents:
diff changeset
4757 void IntervalWalker::walk_to(int lir_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4758 assert(_current_position <= lir_op_id, "can not walk backwards");
a61af66fc99e Initial load
duke
parents:
diff changeset
4759 while (current() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4760 bool is_active = current()->from() <= lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4761 int id = is_active ? current()->from() : lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4762
a61af66fc99e Initial load
duke
parents:
diff changeset
4763 TRACE_LINEAR_SCAN(2, if (_current_position < id) { tty->cr(); tty->print_cr("walk_to(%d) **************************************************************", id); })
a61af66fc99e Initial load
duke
parents:
diff changeset
4764
a61af66fc99e Initial load
duke
parents:
diff changeset
4765 // set _current_position prior to call of walk_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4766 _current_position = id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4767
a61af66fc99e Initial load
duke
parents:
diff changeset
4768 // call walk_to even if _current_position == id
a61af66fc99e Initial load
duke
parents:
diff changeset
4769 walk_to(activeState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4770 walk_to(inactiveState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4771
a61af66fc99e Initial load
duke
parents:
diff changeset
4772 if (is_active) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4773 current()->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4774 if (activate_current()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4775 append_sorted(active_first_addr(current_kind()), current());
a61af66fc99e Initial load
duke
parents:
diff changeset
4776 interval_moved(current(), current_kind(), unhandledState, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4777 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4778
a61af66fc99e Initial load
duke
parents:
diff changeset
4779 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4780 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4781 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4783 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4784 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4785
a61af66fc99e Initial load
duke
parents:
diff changeset
4786 void IntervalWalker::interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4787 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4788 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4789 #define print_state(state) \
a61af66fc99e Initial load
duke
parents:
diff changeset
4790 switch(state) {\
a61af66fc99e Initial load
duke
parents:
diff changeset
4791 case unhandledState: tty->print("unhandled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4792 case activeState: tty->print("active"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4793 case inactiveState: tty->print("inactive"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4794 case handledState: tty->print("handled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4795 default: ShouldNotReachHere(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
4796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4797
a61af66fc99e Initial load
duke
parents:
diff changeset
4798 print_state(from); tty->print(" to "); print_state(to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4799 tty->fill_to(23);
a61af66fc99e Initial load
duke
parents:
diff changeset
4800 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4801
a61af66fc99e Initial load
duke
parents:
diff changeset
4802 #undef print_state
a61af66fc99e Initial load
duke
parents:
diff changeset
4803 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4804 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4805 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4806
a61af66fc99e Initial load
duke
parents:
diff changeset
4807
a61af66fc99e Initial load
duke
parents:
diff changeset
4808
a61af66fc99e Initial load
duke
parents:
diff changeset
4809 // **** Implementation of LinearScanWalker **************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4810
a61af66fc99e Initial load
duke
parents:
diff changeset
4811 LinearScanWalker::LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4812 : IntervalWalker(allocator, unhandled_fixed_first, unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4813 , _move_resolver(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4814 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4815 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4816 _spill_intervals[i] = new IntervalList(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4818 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4819
a61af66fc99e Initial load
duke
parents:
diff changeset
4820
a61af66fc99e Initial load
duke
parents:
diff changeset
4821 inline void LinearScanWalker::init_use_lists(bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4822 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4823 _use_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4824
a61af66fc99e Initial load
duke
parents:
diff changeset
4825 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4826 _block_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4827 _spill_intervals[i]->clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
4828 }
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 inline void LinearScanWalker::exclude_from_use(int reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4833 assert(reg < LinearScan::nof_regs, "interval must have a register assigned (stack slots not allowed)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4834 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4835 _use_pos[reg] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4836 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4838 inline void LinearScanWalker::exclude_from_use(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4839 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4840
a61af66fc99e Initial load
duke
parents:
diff changeset
4841 exclude_from_use(i->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4842 exclude_from_use(i->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
4843 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4844
a61af66fc99e Initial load
duke
parents:
diff changeset
4845 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
4846 assert(use_pos != 0, "must use exclude_from_use to set use_pos to 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
4847
a61af66fc99e Initial load
duke
parents:
diff changeset
4848 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4849 if (_use_pos[reg] > use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4850 _use_pos[reg] = use_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4851 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4852 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4853 _spill_intervals[reg]->append(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4854 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4855 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4856 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4857 inline void LinearScanWalker::set_use_pos(Interval* i, int use_pos, bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4858 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4859 if (use_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4860 set_use_pos(i->assigned_reg(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4861 set_use_pos(i->assigned_regHi(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4862 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4863 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4864
a61af66fc99e Initial load
duke
parents:
diff changeset
4865 inline void LinearScanWalker::set_block_pos(int reg, Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4866 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4867 if (_block_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4868 _block_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4869 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4870 if (_use_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4871 _use_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4872 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4873 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4874 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4875 inline void LinearScanWalker::set_block_pos(Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4876 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4877 if (block_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4878 set_block_pos(i->assigned_reg(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4879 set_block_pos(i->assigned_regHi(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4880 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4881 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4882
a61af66fc99e Initial load
duke
parents:
diff changeset
4883
a61af66fc99e Initial load
duke
parents:
diff changeset
4884 void LinearScanWalker::free_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4885 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4886 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4887 assert(list->assigned_reg() < LinearScan::nof_regs, "active interval must have a register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4888 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4889 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4890 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4891 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4892
a61af66fc99e Initial load
duke
parents:
diff changeset
4893 void LinearScanWalker::free_exclude_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4894 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4895 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4896 exclude_from_use(list);
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::free_collect_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4902 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4903 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4904 if (cur->to() <= list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4905 assert(list->current_intersects_at(cur) == -1, "must not intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4906 set_use_pos(list, list->current_from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4907 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4908 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4910 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4911 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4912 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4913
a61af66fc99e Initial load
duke
parents:
diff changeset
4914 void LinearScanWalker::free_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4915 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4916 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4917 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4918 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4919 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4920 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4921
a61af66fc99e Initial load
duke
parents:
diff changeset
4922 void LinearScanWalker::free_collect_unhandled(IntervalKind kind, Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4923 Interval* list = unhandled_first(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4924 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4925 set_use_pos(list, list->intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4926 if (kind == fixedKind && cur->to() <= list->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4927 set_use_pos(list, list->from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4928 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4929 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4930 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4931 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4932
a61af66fc99e Initial load
duke
parents:
diff changeset
4933 void LinearScanWalker::spill_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4934 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4935 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4936 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4937 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4939 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4940
a61af66fc99e Initial load
duke
parents:
diff changeset
4941 void LinearScanWalker::spill_block_unhandled_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4942 Interval* list = unhandled_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4943 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4944 set_block_pos(list, list->intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4945 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4946 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4948
a61af66fc99e Initial load
duke
parents:
diff changeset
4949 void LinearScanWalker::spill_block_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4950 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4951 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4952 if (cur->to() > list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4953 set_block_pos(list, list->current_intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4954 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4955 assert(list->current_intersects_at(cur) == -1, "invalid optimization: intervals intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4956 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4957
a61af66fc99e Initial load
duke
parents:
diff changeset
4958 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4959 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4960 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4961
a61af66fc99e Initial load
duke
parents:
diff changeset
4962 void LinearScanWalker::spill_collect_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4963 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4964 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4965 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4966 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4968 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4969
a61af66fc99e Initial load
duke
parents:
diff changeset
4970 void LinearScanWalker::spill_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4971 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4972 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4973 if (list->current_intersects(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4974 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4975 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4976 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4977 }
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 void LinearScanWalker::insert_move(int op_id, Interval* src_it, Interval* dst_it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4982 // output all moves here. When source and target are equal, the move is
a61af66fc99e Initial load
duke
parents:
diff changeset
4983 // optimized away later in assign_reg_nums
a61af66fc99e Initial load
duke
parents:
diff changeset
4984
a61af66fc99e Initial load
duke
parents:
diff changeset
4985 op_id = (op_id + 1) & ~1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4986 BlockBegin* op_block = allocator()->block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4987 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
4988
a61af66fc99e Initial load
duke
parents:
diff changeset
4989 // calculate index of instruction inside instruction list of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
4990 // the minimal index (for a block with no spill moves) can be calculated because the
a61af66fc99e Initial load
duke
parents:
diff changeset
4991 // numbering of instructions is known.
a61af66fc99e Initial load
duke
parents:
diff changeset
4992 // When the block already contains spill moves, the index must be increased until the
a61af66fc99e Initial load
duke
parents:
diff changeset
4993 // correct index is reached.
a61af66fc99e Initial load
duke
parents:
diff changeset
4994 LIR_OpList* list = op_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
4995 int index = (op_id - list->at(0)->id()) / 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4996 assert(list->at(index)->id() <= op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4997
a61af66fc99e Initial load
duke
parents:
diff changeset
4998 while (list->at(index)->id() != op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4999 index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
5000 assert(0 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
5001 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5002 assert(1 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
5003 assert(list->at(index)->id() == op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
5004
a61af66fc99e Initial load
duke
parents:
diff changeset
5005 // insert new instruction before instruction at position index
a61af66fc99e Initial load
duke
parents:
diff changeset
5006 _move_resolver.move_insert_position(op_block->lir(), index - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5007 _move_resolver.add_mapping(src_it, dst_it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5009
a61af66fc99e Initial load
duke
parents:
diff changeset
5010
a61af66fc99e Initial load
duke
parents:
diff changeset
5011 int LinearScanWalker::find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5012 int from_block_nr = min_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5013 int to_block_nr = max_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5014
a61af66fc99e Initial load
duke
parents:
diff changeset
5015 assert(0 <= from_block_nr && from_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5016 assert(0 <= to_block_nr && to_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5017 assert(from_block_nr < to_block_nr, "must cross block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5018
a61af66fc99e Initial load
duke
parents:
diff changeset
5019 // Try to split at end of max_block. If this would be after
a61af66fc99e Initial load
duke
parents:
diff changeset
5020 // max_split_pos, then use the begin of max_block
a61af66fc99e Initial load
duke
parents:
diff changeset
5021 int optimal_split_pos = max_block->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5022 if (optimal_split_pos > max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5023 optimal_split_pos = max_block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
5024 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5025
a61af66fc99e Initial load
duke
parents:
diff changeset
5026 int min_loop_depth = max_block->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
5027 for (int i = to_block_nr - 1; i >= from_block_nr; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5028 BlockBegin* cur = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5029
a61af66fc99e Initial load
duke
parents:
diff changeset
5030 if (cur->loop_depth() < min_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5031 // block with lower loop-depth found -> split at the end of this block
a61af66fc99e Initial load
duke
parents:
diff changeset
5032 min_loop_depth = cur->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
5033 optimal_split_pos = cur->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5034 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5035 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5036 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
5037
a61af66fc99e Initial load
duke
parents:
diff changeset
5038 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5040
a61af66fc99e Initial load
duke
parents:
diff changeset
5041
a61af66fc99e Initial load
duke
parents:
diff changeset
5042 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
5043 int optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5044 if (min_split_pos == max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5045 // trivial case, no optimization of split position possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5046 TRACE_LINEAR_SCAN(4, tty->print_cr(" min-pos and max-pos are equal, no optimization possible"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5047 optimal_split_pos = min_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5048
a61af66fc99e Initial load
duke
parents:
diff changeset
5049 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5050 assert(min_split_pos < max_split_pos, "must be true then");
a61af66fc99e Initial load
duke
parents:
diff changeset
5051 assert(min_split_pos > 0, "cannot access min_split_pos - 1 otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5052
a61af66fc99e Initial load
duke
parents:
diff changeset
5053 // reason for using min_split_pos - 1: when the minimal split pos is exactly at the
a61af66fc99e Initial load
duke
parents:
diff changeset
5054 // beginning of a block, then min_split_pos is also a possible split position.
a61af66fc99e Initial load
duke
parents:
diff changeset
5055 // 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
5056 BlockBegin* min_block = allocator()->block_of_op_with_id(min_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5057
a61af66fc99e Initial load
duke
parents:
diff changeset
5058 // reason for using max_split_pos - 1: otherwise there would be an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
5059 // when an interval ends at the end of the last block of the method
a61af66fc99e Initial load
duke
parents:
diff changeset
5060 // (in this case, max_split_pos == allocator()->max_lir_op_id() + 2, and there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
5061 // block at this op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5062 BlockBegin* max_block = allocator()->block_of_op_with_id(max_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5063
a61af66fc99e Initial load
duke
parents:
diff changeset
5064 assert(min_block->linear_scan_number() <= max_block->linear_scan_number(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5065 if (min_block == max_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5066 // split position cannot be moved to block boundary, so split as late as possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5067 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
5068 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5069
a61af66fc99e Initial load
duke
parents:
diff changeset
5070 } 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
5071 // Do not move split position if the interval has a hole before max_split_pos.
a61af66fc99e Initial load
duke
parents:
diff changeset
5072 // Intervals resulting from Phi-Functions have more than one definition (marked
a61af66fc99e Initial load
duke
parents:
diff changeset
5073 // as mustHaveRegister) with a hole before each definition. When the register is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5074 // for the second definition, an earlier reloading is unnecessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
5075 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
5076 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5077
a61af66fc99e Initial load
duke
parents:
diff changeset
5078 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5079 // seach optimal block boundary between min_split_pos and max_split_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5080 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
5081
a61af66fc99e Initial load
duke
parents:
diff changeset
5082 if (do_loop_optimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5083 // Loop optimization: if a loop-end marker is found between min- and max-position,
a61af66fc99e Initial load
duke
parents:
diff changeset
5084 // then split before this loop
a61af66fc99e Initial load
duke
parents:
diff changeset
5085 int loop_end_pos = it->next_usage_exact(loopEndMarker, min_block->last_lir_instruction_id() + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5086 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
5087
a61af66fc99e Initial load
duke
parents:
diff changeset
5088 assert(loop_end_pos > min_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5089 if (loop_end_pos < max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5090 // loop-end marker found between min- and max-position
a61af66fc99e Initial load
duke
parents:
diff changeset
5091 // if it is not the end marker for the same loop as the min-position, then move
a61af66fc99e Initial load
duke
parents:
diff changeset
5092 // the max-position to this loop block.
a61af66fc99e Initial load
duke
parents:
diff changeset
5093 // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5094 // of the interval (normally, only mustHaveRegister causes a reloading)
a61af66fc99e Initial load
duke
parents:
diff changeset
5095 BlockBegin* loop_block = allocator()->block_of_op_with_id(loop_end_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5096
a61af66fc99e Initial load
duke
parents:
diff changeset
5097 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
5098 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
5099
a61af66fc99e Initial load
duke
parents:
diff changeset
5100 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
5101 if (optimal_split_pos == loop_block->last_lir_instruction_id() + 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5102 optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5103 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization not necessary"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5104 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5105 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization successful"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5109
a61af66fc99e Initial load
duke
parents:
diff changeset
5110 if (optimal_split_pos == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5111 // not calculated by loop optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5112 optimal_split_pos = find_optimal_split_pos(min_block, max_block, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5114 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5116 TRACE_LINEAR_SCAN(4, tty->print_cr(" optimal split position: %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5117
a61af66fc99e Initial load
duke
parents:
diff changeset
5118 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5120
a61af66fc99e Initial load
duke
parents:
diff changeset
5121
a61af66fc99e Initial load
duke
parents:
diff changeset
5122 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5123 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5124 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5125 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5126 2) the right part is sorted into to the unhandled-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5127 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5128 void LinearScanWalker::split_before_usage(Interval* it, int min_split_pos, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5129 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5130 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5131
a61af66fc99e Initial load
duke
parents:
diff changeset
5132 assert(it->from() < min_split_pos, "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5133 assert(current_position() < min_split_pos, "cannot split before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5134 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5135 assert(max_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5136
a61af66fc99e Initial load
duke
parents:
diff changeset
5137 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5138
a61af66fc99e Initial load
duke
parents:
diff changeset
5139 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5140 assert(optimal_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5141 assert(optimal_split_pos > it->from(), "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5142
a61af66fc99e Initial load
duke
parents:
diff changeset
5143 if (optimal_split_pos == it->to() && it->next_usage(mustHaveRegister, min_split_pos) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5144 // the split position would be just before the end of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5145 // -> no split at all necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5146 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
5147 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5149
a61af66fc99e Initial load
duke
parents:
diff changeset
5150 // 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
5151 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
5152
a61af66fc99e Initial load
duke
parents:
diff changeset
5153 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5154 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5155 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5157
a61af66fc99e Initial load
duke
parents:
diff changeset
5158 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5159 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
5160 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
5161
a61af66fc99e Initial load
duke
parents:
diff changeset
5162 Interval* split_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5163
a61af66fc99e Initial load
duke
parents:
diff changeset
5164 allocator()->append_interval(split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5165 allocator()->copy_register_flags(it, split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5166 split_part->set_insert_move_when_activated(move_necessary);
a61af66fc99e Initial load
duke
parents:
diff changeset
5167 append_to_unhandled(unhandled_first_addr(anyKind), split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5168
a61af66fc99e Initial load
duke
parents:
diff changeset
5169 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
5170 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5171 TRACE_LINEAR_SCAN(2, tty->print (" "); split_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5172 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5173
a61af66fc99e Initial load
duke
parents:
diff changeset
5174 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5175 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5176 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5177 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5178 2) the right part is always on the stack and therefore ignored in further processing
a61af66fc99e Initial load
duke
parents:
diff changeset
5179 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5180 void LinearScanWalker::split_for_spilling(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5181 // calculate allowed range of splitting position
a61af66fc99e Initial load
duke
parents:
diff changeset
5182 int max_split_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5183 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, max_split_pos) + 1, it->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5184
a61af66fc99e Initial load
duke
parents:
diff changeset
5185 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting and spilling interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5186 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5187
a61af66fc99e Initial load
duke
parents:
diff changeset
5188 assert(it->state() == activeState, "why spill interval that is not active?");
a61af66fc99e Initial load
duke
parents:
diff changeset
5189 assert(it->from() <= min_split_pos, "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5190 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5191 assert(max_split_pos < it->to(), "cannot split at end end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5192 assert(current_position() < it->to(), "interval must not end before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5193
a61af66fc99e Initial load
duke
parents:
diff changeset
5194 if (min_split_pos == it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5195 // the whole interval is never used, so spill it entirely to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
5196 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
5197 assert(it->first_usage(shouldHaveRegister) > current_position(), "interval must not have use position before current_position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5198
a61af66fc99e Initial load
duke
parents:
diff changeset
5199 allocator()->assign_spill_slot(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5200 allocator()->change_spill_state(it, min_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5201
a61af66fc99e Initial load
duke
parents:
diff changeset
5202 // Also kick parent intervals out of register to memory when they have no use
a61af66fc99e Initial load
duke
parents:
diff changeset
5203 // position. This avoids short interval in register surrounded by intervals in
a61af66fc99e Initial load
duke
parents:
diff changeset
5204 // memory -> avoid useless moves from memory to register and back
a61af66fc99e Initial load
duke
parents:
diff changeset
5205 Interval* parent = it;
a61af66fc99e Initial load
duke
parents:
diff changeset
5206 while (parent != NULL && parent->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5207 parent = parent->split_child_before_op_id(parent->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5208
a61af66fc99e Initial load
duke
parents:
diff changeset
5209 if (parent->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5210 if (parent->first_usage(shouldHaveRegister) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5211 // parent is never used, so kick it out of its assigned register
a61af66fc99e Initial load
duke
parents:
diff changeset
5212 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
5213 allocator()->assign_spill_slot(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
5214 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5215 // do not go further back because the register is actually used by the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5216 parent = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5220
a61af66fc99e Initial load
duke
parents:
diff changeset
5221 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5222 // search optimal split pos, split interval and spill only the right hand part
a61af66fc99e Initial load
duke
parents:
diff changeset
5223 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5224
a61af66fc99e Initial load
duke
parents:
diff changeset
5225 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5226 assert(optimal_split_pos < it->to(), "cannot split at end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5227 assert(optimal_split_pos >= it->from(), "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5228
a61af66fc99e Initial load
duke
parents:
diff changeset
5229 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5230 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5231 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5232 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5233
a61af66fc99e Initial load
duke
parents:
diff changeset
5234 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5235 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
5236 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
5237
a61af66fc99e Initial load
duke
parents:
diff changeset
5238 Interval* spilled_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5239 allocator()->append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5240 allocator()->assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5241 allocator()->change_spill_state(spilled_part, optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5242
a61af66fc99e Initial load
duke
parents:
diff changeset
5243 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5244 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
5245 insert_move(optimal_split_pos, it, spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5247
a61af66fc99e Initial load
duke
parents:
diff changeset
5248 // the current_split_child is needed later when moves are inserted for reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5249 assert(spilled_part->current_split_child() == it, "overwriting wrong current_split_child");
a61af66fc99e Initial load
duke
parents:
diff changeset
5250 spilled_part->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5251
a61af66fc99e Initial load
duke
parents:
diff changeset
5252 TRACE_LINEAR_SCAN(2, tty->print_cr(" split interval in two parts"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5253 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5254 TRACE_LINEAR_SCAN(2, tty->print (" "); spilled_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5255 }
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 void LinearScanWalker::split_stack_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5260 int min_split_pos = current_position() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5261 int max_split_pos = MIN2(it->first_usage(shouldHaveRegister), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5262
a61af66fc99e Initial load
duke
parents:
diff changeset
5263 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5265
a61af66fc99e Initial load
duke
parents:
diff changeset
5266 void LinearScanWalker::split_when_partial_register_available(Interval* it, int register_available_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5267 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, register_available_until), it->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5268 int max_split_pos = register_available_until;
a61af66fc99e Initial load
duke
parents:
diff changeset
5269
a61af66fc99e Initial load
duke
parents:
diff changeset
5270 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5272
a61af66fc99e Initial load
duke
parents:
diff changeset
5273 void LinearScanWalker::split_and_spill_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5274 assert(it->state() == activeState || it->state() == inactiveState, "other states not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5275
a61af66fc99e Initial load
duke
parents:
diff changeset
5276 int current_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5277 if (it->state() == inactiveState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5278 // the interval is currently inactive, so no spill slot is needed for now.
a61af66fc99e Initial load
duke
parents:
diff changeset
5279 // when the split part is activated, the interval has a new chance to get a register,
a61af66fc99e Initial load
duke
parents:
diff changeset
5280 // so in the best case no stack slot is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5281 assert(it->has_hole_between(current_pos - 1, current_pos + 1), "interval can not be inactive otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5282 split_before_usage(it, current_pos + 1, current_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5283
a61af66fc99e Initial load
duke
parents:
diff changeset
5284 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5285 // search the position where the interval must have a register and split
a61af66fc99e Initial load
duke
parents:
diff changeset
5286 // at the optimal position before.
a61af66fc99e Initial load
duke
parents:
diff changeset
5287 // The new created part is added to the unhandled list and will get a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5288 // when it is activated
a61af66fc99e Initial load
duke
parents:
diff changeset
5289 int min_split_pos = current_pos + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5290 int max_split_pos = MIN2(it->next_usage(mustHaveRegister, min_split_pos), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5291
a61af66fc99e Initial load
duke
parents:
diff changeset
5292 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5293
a61af66fc99e Initial load
duke
parents:
diff changeset
5294 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
5295 split_for_spilling(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5296 }
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 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
5301 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5302 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5303
a61af66fc99e Initial load
duke
parents:
diff changeset
5304 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5305 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5306 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5307
a61af66fc99e Initial load
duke
parents:
diff changeset
5308 } else if (_use_pos[i] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5309 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5310 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
5311 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5312 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5313 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5314 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5315 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
5316 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5318 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5320
a61af66fc99e Initial load
duke
parents:
diff changeset
5321 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5322 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5323 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5324 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5325 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5326 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5327 return any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5328 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5329 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5330
a61af66fc99e Initial load
duke
parents:
diff changeset
5331 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
5332 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5333
a61af66fc99e Initial load
duke
parents:
diff changeset
5334 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5335 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5336
a61af66fc99e Initial load
duke
parents:
diff changeset
5337 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5338 if (_use_pos[i] >= interval_to && _use_pos[i + 1] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5339 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5340 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
5341 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5343 } else if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5344 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5345 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
5346 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5347 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5349 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5350
a61af66fc99e Initial load
duke
parents:
diff changeset
5351 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5352 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5353 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5354 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5355 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5356 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5357 return any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5359 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5360
a61af66fc99e Initial load
duke
parents:
diff changeset
5361
a61af66fc99e Initial load
duke
parents:
diff changeset
5362 bool LinearScanWalker::alloc_free_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5363 TRACE_LINEAR_SCAN(2, tty->print("trying to find free register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5364
a61af66fc99e Initial load
duke
parents:
diff changeset
5365 init_use_lists(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5366 free_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5367 free_exclude_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5368 free_collect_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5369 free_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5370 // free_collect_unhandled(fixedKind, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5371 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
5372
a61af66fc99e Initial load
duke
parents:
diff changeset
5373 // _use_pos contains the start of the next interval that has this register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5374 // (either as a fixed register or a normal allocated register in the past)
a61af66fc99e Initial load
duke
parents:
diff changeset
5375 // only intervals overlapping with cur are processed, non-overlapping invervals can be ignored safely
a61af66fc99e Initial load
duke
parents:
diff changeset
5376 TRACE_LINEAR_SCAN(4, tty->print_cr(" state of registers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5377 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
5378
a61af66fc99e Initial load
duke
parents:
diff changeset
5379 int hint_reg, hint_regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5380 Interval* register_hint = cur->register_hint();
a61af66fc99e Initial load
duke
parents:
diff changeset
5381 if (register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5382 hint_reg = register_hint->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5383 hint_regHi = register_hint->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
5384
a61af66fc99e Initial load
duke
parents:
diff changeset
5385 if (allocator()->is_precolored_cpu_interval(register_hint)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5386 assert(hint_reg != any_reg && hint_regHi == any_reg, "must be for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
5387 hint_regHi = hint_reg + 1; // connect e.g. eax-edx
a61af66fc99e Initial load
duke
parents:
diff changeset
5388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5389 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
5390
a61af66fc99e Initial load
duke
parents:
diff changeset
5391 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5392 hint_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5393 hint_regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5394 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5395 assert(hint_reg == any_reg || hint_reg != hint_regHi, "hint reg and regHi equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
5396 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned to interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5397
a61af66fc99e Initial load
duke
parents:
diff changeset
5398 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5399 int reg_needed_until = cur->from() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5400 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5401
a61af66fc99e Initial load
duke
parents:
diff changeset
5402 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5403 int split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5404 int reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5405 int regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5406
a61af66fc99e Initial load
duke
parents:
diff changeset
5407 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5408 reg = find_free_double_reg(reg_needed_until, interval_to, hint_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5409 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5410 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5411 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5413 split_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5414
a61af66fc99e Initial load
duke
parents:
diff changeset
5415 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5416 reg = find_free_reg(reg_needed_until, interval_to, hint_reg, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5417 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5418 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5419 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5420 split_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5421
a61af66fc99e Initial load
duke
parents:
diff changeset
5422 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5423 regHi = find_free_reg(reg_needed_until, interval_to, hint_regHi, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5424
a61af66fc99e Initial load
duke
parents:
diff changeset
5425 if (_use_pos[reg] < interval_to && regHi == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5426 // do not split interval if only one register can be assigned until the split pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5427 // (when one register is found for the whole interval, split&spill is only
a61af66fc99e Initial load
duke
parents:
diff changeset
5428 // performed for the hi register)
a61af66fc99e Initial load
duke
parents:
diff changeset
5429 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5430
a61af66fc99e Initial load
duke
parents:
diff changeset
5431 } else if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5432 split_pos = MIN2(split_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5433
a61af66fc99e Initial load
duke
parents:
diff changeset
5434 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5435 if (reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5436 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5437 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5438 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5441 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5442 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5443
a61af66fc99e Initial load
duke
parents:
diff changeset
5444 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5445 TRACE_LINEAR_SCAN(2, tty->print_cr("selected register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5446
a61af66fc99e Initial load
duke
parents:
diff changeset
5447 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5448 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5449 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5450 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5451 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5452
a61af66fc99e Initial load
duke
parents:
diff changeset
5453 // only return true if interval is completely assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5454 return _num_phys_regs == 1 || regHi != any_reg;
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 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
5459 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5460
a61af66fc99e Initial load
duke
parents:
diff changeset
5461 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5462 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5463 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5464
a61af66fc99e Initial load
duke
parents:
diff changeset
5465 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5466 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
5467 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5468 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5469 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5471
a61af66fc99e Initial load
duke
parents:
diff changeset
5472 if (max_reg != any_reg && _block_pos[max_reg] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5473 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5475
a61af66fc99e Initial load
duke
parents:
diff changeset
5476 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5477 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5478
a61af66fc99e Initial load
duke
parents:
diff changeset
5479 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
5480 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5481
a61af66fc99e Initial load
duke
parents:
diff changeset
5482 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5483
a61af66fc99e Initial load
duke
parents:
diff changeset
5484 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5485 if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5486 if (max_reg == any_reg || _use_pos[i] > _use_pos[max_reg]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5487 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5491
a61af66fc99e Initial load
duke
parents:
diff changeset
5492 if (_block_pos[max_reg] <= interval_to || _block_pos[max_reg + 1] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5493 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5494 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5495
a61af66fc99e Initial load
duke
parents:
diff changeset
5496 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5498
a61af66fc99e Initial load
duke
parents:
diff changeset
5499 void LinearScanWalker::split_and_spill_intersecting_intervals(int reg, int regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5500 assert(reg != any_reg, "no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5501
a61af66fc99e Initial load
duke
parents:
diff changeset
5502 for (int i = 0; i < _spill_intervals[reg]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5503 Interval* it = _spill_intervals[reg]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5504 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5505 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5507
a61af66fc99e Initial load
duke
parents:
diff changeset
5508 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5509 IntervalList* processed = _spill_intervals[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5510 for (int i = 0; i < _spill_intervals[regHi]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5511 Interval* it = _spill_intervals[regHi]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5512 if (processed->index_of(it) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5513 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5514 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5515 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5517 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5518 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5519
a61af66fc99e Initial load
duke
parents:
diff changeset
5520
a61af66fc99e Initial load
duke
parents:
diff changeset
5521 // Split an Interval and spill it to memory so that cur can be placed in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5522 void LinearScanWalker::alloc_locked_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5523 TRACE_LINEAR_SCAN(2, tty->print("need to split and spill to get register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5524
a61af66fc99e Initial load
duke
parents:
diff changeset
5525 // collect current usage of registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5526 init_use_lists(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5527 spill_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5528 // spill_block_unhandled_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5529 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
5530 spill_block_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5531 spill_collect_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5532 spill_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5533
a61af66fc99e Initial load
duke
parents:
diff changeset
5534 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
5535 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5536 tty->print_cr(" state of registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
5537 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5538 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
5539 for (int j = 0; j < _spill_intervals[i]->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5540 tty->print("%d ", _spill_intervals[i]->at(j)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
5541 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5542 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5543 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5545 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5546
a61af66fc99e Initial load
duke
parents:
diff changeset
5547 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5548 int reg_needed_until = MIN2(cur->first_usage(mustHaveRegister), cur->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5549 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5550 assert (reg_needed_until > 0 && reg_needed_until < max_jint, "interval has no use");
a61af66fc99e Initial load
duke
parents:
diff changeset
5551
a61af66fc99e Initial load
duke
parents:
diff changeset
5552 int split_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5553 int use_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5554 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5555 int reg, regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5556
a61af66fc99e Initial load
duke
parents:
diff changeset
5557 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5558 reg = find_locked_double_reg(reg_needed_until, interval_to, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5559 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5560
a61af66fc99e Initial load
duke
parents:
diff changeset
5561 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5562 use_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5563 split_pos = MIN2(_block_pos[reg], _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5564 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5565 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5566 reg = find_locked_reg(reg_needed_until, interval_to, any_reg, cur->assigned_reg(), &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5567 regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5568
a61af66fc99e Initial load
duke
parents:
diff changeset
5569 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5570 use_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5571 split_pos = _block_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5572
a61af66fc99e Initial load
duke
parents:
diff changeset
5573 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5574 if (cur->assigned_reg() != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5575 regHi = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5576 reg = cur->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5577 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5578 regHi = find_locked_reg(reg_needed_until, interval_to, any_reg, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5579 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5580 use_pos = MIN2(use_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5581 split_pos = MIN2(split_pos, _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5582 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5583 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5584
a61af66fc99e Initial load
duke
parents:
diff changeset
5585 if (regHi != any_reg && reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5586 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5587 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5588 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5589 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5590 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5592 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5593 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5594
a61af66fc99e Initial load
duke
parents:
diff changeset
5595 if (reg == any_reg || (_num_phys_regs == 2 && regHi == any_reg) || use_pos <= cur->first_usage(mustHaveRegister)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5596 // the first use of cur is later than the spilling position -> spill cur
a61af66fc99e Initial load
duke
parents:
diff changeset
5597 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
5598
a61af66fc99e Initial load
duke
parents:
diff changeset
5599 if (cur->first_usage(mustHaveRegister) <= cur->from() + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5600 assert(false, "cannot spill interval that is used in first instruction (possible reason: no register found)");
a61af66fc99e Initial load
duke
parents:
diff changeset
5601 // assign a reasonable register and do a bailout in product mode to avoid errors
a61af66fc99e Initial load
duke
parents:
diff changeset
5602 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5603 BAILOUT("LinearScan: no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5605
a61af66fc99e Initial load
duke
parents:
diff changeset
5606 split_and_spill_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5607 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5608 TRACE_LINEAR_SCAN(4, tty->print_cr("decided to use register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5609 assert(reg != any_reg && (_num_phys_regs == 1 || regHi != any_reg), "no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5610 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5611 assert(need_split == false || split_pos > cur->from(), "splitting interval at from");
a61af66fc99e Initial load
duke
parents:
diff changeset
5612
a61af66fc99e Initial load
duke
parents:
diff changeset
5613 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5614 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5615 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5616 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5617 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5618
a61af66fc99e Initial load
duke
parents:
diff changeset
5619 // perform splitting and spilling for all affected intervalls
a61af66fc99e Initial load
duke
parents:
diff changeset
5620 split_and_spill_intersecting_intervals(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5623
a61af66fc99e Initial load
duke
parents:
diff changeset
5624 bool LinearScanWalker::no_allocation_possible(Interval* cur) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
5625 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5626 // fast calculation of intervals that can never get a register because the
a61af66fc99e Initial load
duke
parents:
diff changeset
5627 // the next instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5628 // Note: this does not work if callee-saved registers are available (e.g. on Sparc)
a61af66fc99e Initial load
duke
parents:
diff changeset
5629
a61af66fc99e Initial load
duke
parents:
diff changeset
5630 // check if this interval is the result of a split operation
a61af66fc99e Initial load
duke
parents:
diff changeset
5631 // (an interval got a register until this position)
a61af66fc99e Initial load
duke
parents:
diff changeset
5632 int pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5633 if ((pos & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5634 // the current instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5635 if (pos < allocator()->max_lir_op_id() && allocator()->has_call(pos + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5636 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
5637
a61af66fc99e Initial load
duke
parents:
diff changeset
5638 // safety check that there is really no register available
a61af66fc99e Initial load
duke
parents:
diff changeset
5639 assert(alloc_free_reg(cur) == false, "found a register for this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5640 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5642
a61af66fc99e Initial load
duke
parents:
diff changeset
5643 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5644 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5645 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5647
a61af66fc99e Initial load
duke
parents:
diff changeset
5648 void LinearScanWalker::init_vars_for_alloc(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5649 BasicType type = cur->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
5650 _num_phys_regs = LinearScan::num_physical_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5651 _adjacent_regs = LinearScan::requires_adjacent_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5652
a61af66fc99e Initial load
duke
parents:
diff changeset
5653 if (pd_init_regs_for_alloc(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5654 // the appropriate register range was selected.
a61af66fc99e Initial load
duke
parents:
diff changeset
5655 } else if (type == T_FLOAT || type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5656 _first_reg = pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5657 _last_reg = pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5658 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5659 _first_reg = pd_first_cpu_reg;
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
5660 _last_reg = FrameMap::last_cpu_reg();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5661 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5662
a61af66fc99e Initial load
duke
parents:
diff changeset
5663 assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5664 assert(0 <= _last_reg && _last_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5665 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5666
a61af66fc99e Initial load
duke
parents:
diff changeset
5667
a61af66fc99e Initial load
duke
parents:
diff changeset
5668 bool LinearScanWalker::is_move(LIR_Op* op, Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5669 if (op->code() != lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5670 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5671 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5672 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5673
a61af66fc99e Initial load
duke
parents:
diff changeset
5674 LIR_Opr in = ((LIR_Op1*)op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5675 LIR_Opr res = ((LIR_Op1*)op)->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5676 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
5677 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5678
a61af66fc99e Initial load
duke
parents:
diff changeset
5679 // optimization (especially for phi functions of nested loops):
a61af66fc99e Initial load
duke
parents:
diff changeset
5680 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5681 void LinearScanWalker::combine_spilled_intervals(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5682 if (cur->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5683 // optimization is only suitable for split parents
a61af66fc99e Initial load
duke
parents:
diff changeset
5684 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5685 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5686
a61af66fc99e Initial load
duke
parents:
diff changeset
5687 Interval* register_hint = cur->register_hint(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5688 if (register_hint == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5689 // cur is not the target of a move, otherwise register_hint would be set
a61af66fc99e Initial load
duke
parents:
diff changeset
5690 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5691 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5692 assert(register_hint->is_split_parent(), "register hint must be split parent");
a61af66fc99e Initial load
duke
parents:
diff changeset
5693
a61af66fc99e Initial load
duke
parents:
diff changeset
5694 if (cur->spill_state() != noOptimization || register_hint->spill_state() != noOptimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5695 // combining the stack slots for intervals where spill move optimization is applied
a61af66fc99e Initial load
duke
parents:
diff changeset
5696 // is not benefitial and would cause problems
a61af66fc99e Initial load
duke
parents:
diff changeset
5697 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5698 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5699
a61af66fc99e Initial load
duke
parents:
diff changeset
5700 int begin_pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5701 int end_pos = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5702 if (end_pos > allocator()->max_lir_op_id() || (begin_pos & 1) != 0 || (end_pos & 1) != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5703 // safety check that lir_op_with_id is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
5704 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5705 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5706
a61af66fc99e Initial load
duke
parents:
diff changeset
5707 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
5708 // cur and register_hint are not connected with two moves
a61af66fc99e Initial load
duke
parents:
diff changeset
5709 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5710 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5711
a61af66fc99e Initial load
duke
parents:
diff changeset
5712 Interval* begin_hint = register_hint->split_child_at_op_id(begin_pos, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5713 Interval* end_hint = register_hint->split_child_at_op_id(end_pos, LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5714 if (begin_hint == end_hint || begin_hint->to() != begin_pos || end_hint->from() != end_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5715 // register_hint must be split, otherwise the re-writing of use positions does not work
a61af66fc99e Initial load
duke
parents:
diff changeset
5716 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5718
a61af66fc99e Initial load
duke
parents:
diff changeset
5719 assert(begin_hint->assigned_reg() != any_reg, "must have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5720 assert(end_hint->assigned_reg() == any_reg, "must not have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5721 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
5722 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
5723
a61af66fc99e Initial load
duke
parents:
diff changeset
5724 if (begin_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5725 // 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
5726 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5728 assert(register_hint->canonical_spill_slot() != -1, "must be set when part of interval was spilled");
a61af66fc99e Initial load
duke
parents:
diff changeset
5729
a61af66fc99e Initial load
duke
parents:
diff changeset
5730 // modify intervals such that cur gets the same stack slot as register_hint
a61af66fc99e Initial load
duke
parents:
diff changeset
5731 // delete use positions to prevent the intervals to get a register at beginning
a61af66fc99e Initial load
duke
parents:
diff changeset
5732 cur->set_canonical_spill_slot(register_hint->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
5733 cur->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5734 end_hint->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5735 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5736
a61af66fc99e Initial load
duke
parents:
diff changeset
5737
a61af66fc99e Initial load
duke
parents:
diff changeset
5738 // allocate a physical register or memory location to an interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5739 bool LinearScanWalker::activate_current() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5740 Interval* cur = current();
a61af66fc99e Initial load
duke
parents:
diff changeset
5741 bool result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5742
a61af66fc99e Initial load
duke
parents:
diff changeset
5743 TRACE_LINEAR_SCAN(2, tty->print ("+++++ activating interval "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5744 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
5745
a61af66fc99e Initial load
duke
parents:
diff changeset
5746 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5747 // activating an interval that has a stack slot assigned -> split it at first use position
a61af66fc99e Initial load
duke
parents:
diff changeset
5748 // used for method parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
5749 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
5750
a61af66fc99e Initial load
duke
parents:
diff changeset
5751 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5752 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5753
a61af66fc99e Initial load
duke
parents:
diff changeset
5754 } else if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5755 // activating an interval that must start in a stack slot, but may get a register later
a61af66fc99e Initial load
duke
parents:
diff changeset
5756 // used for lir_roundfp: rounding is done by store to stack and reload later
a61af66fc99e Initial load
duke
parents:
diff changeset
5757 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
5758 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5759
a61af66fc99e Initial load
duke
parents:
diff changeset
5760 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5761 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5762 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5763
a61af66fc99e Initial load
duke
parents:
diff changeset
5764 } else if (cur->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5765 // interval has not assigned register -> normal allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
5766 // (this is the normal case for most intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
5767 TRACE_LINEAR_SCAN(4, tty->print_cr(" normal allocation of register"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5768
a61af66fc99e Initial load
duke
parents:
diff changeset
5769 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5770 combine_spilled_intervals(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5771
a61af66fc99e Initial load
duke
parents:
diff changeset
5772 init_vars_for_alloc(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5773 if (no_allocation_possible(cur) || !alloc_free_reg(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5774 // no empty register available.
a61af66fc99e Initial load
duke
parents:
diff changeset
5775 // split and spill another interval so that this interval gets a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5776 alloc_locked_reg(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5777 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5778
a61af66fc99e Initial load
duke
parents:
diff changeset
5779 // spilled intervals need not be move to active-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5780 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5781 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5782 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5783 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5784
a61af66fc99e Initial load
duke
parents:
diff changeset
5785 // load spilled values that become active from stack slot to register
a61af66fc99e Initial load
duke
parents:
diff changeset
5786 if (cur->insert_move_when_activated()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5787 assert(cur->is_split_child(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5788 assert(cur->current_split_child() != NULL, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5789 assert(cur->current_split_child()->reg_num() != cur->reg_num(), "cannot insert move between same interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5790 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
5791
a61af66fc99e Initial load
duke
parents:
diff changeset
5792 insert_move(cur->from(), cur->current_split_child(), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5793 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5794 cur->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5795
a61af66fc99e Initial load
duke
parents:
diff changeset
5796 return result; // true = interval is moved to active list
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 // Implementation of EdgeMoveOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
5801
a61af66fc99e Initial load
duke
parents:
diff changeset
5802 EdgeMoveOptimizer::EdgeMoveOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
5803 _edge_instructions(4),
a61af66fc99e Initial load
duke
parents:
diff changeset
5804 _edge_instructions_idx(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
5805 {
a61af66fc99e Initial load
duke
parents:
diff changeset
5806 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5807
a61af66fc99e Initial load
duke
parents:
diff changeset
5808 void EdgeMoveOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5809 EdgeMoveOptimizer optimizer = EdgeMoveOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
5810
a61af66fc99e Initial load
duke
parents:
diff changeset
5811 // ignore the first block in the list (index 0 is not processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
5812 for (int i = code->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5813 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5814
a61af66fc99e Initial load
duke
parents:
diff changeset
5815 if (block->number_of_preds() > 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5816 optimizer.optimize_moves_at_block_end(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5818 if (block->number_of_sux() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5819 optimizer.optimize_moves_at_block_begin(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5821 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5822 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5823
a61af66fc99e Initial load
duke
parents:
diff changeset
5824
a61af66fc99e Initial load
duke
parents:
diff changeset
5825 // clear all internal data structures
a61af66fc99e Initial load
duke
parents:
diff changeset
5826 void EdgeMoveOptimizer::init_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5827 _edge_instructions.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5828 _edge_instructions_idx.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5829 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5830
a61af66fc99e Initial load
duke
parents:
diff changeset
5831 // append a lir-instruction-list and the index of the current operation in to the list
a61af66fc99e Initial load
duke
parents:
diff changeset
5832 void EdgeMoveOptimizer::append_instructions(LIR_OpList* instructions, int instructions_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5833 _edge_instructions.append(instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
5834 _edge_instructions_idx.append(instructions_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5835 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5836
a61af66fc99e Initial load
duke
parents:
diff changeset
5837 // return the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5838 LIR_Op* EdgeMoveOptimizer::instruction_at(int edge) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5839 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5840 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5841
a61af66fc99e Initial load
duke
parents:
diff changeset
5842 if (idx < instructions->length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5843 return instructions->at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5844 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5845 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5846 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5847 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5848
a61af66fc99e Initial load
duke
parents:
diff changeset
5849 // removes the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5850 void EdgeMoveOptimizer::remove_cur_instruction(int edge, bool decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5851 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5852 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5853 instructions->remove_at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5854
a61af66fc99e Initial load
duke
parents:
diff changeset
5855 if (decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5856 _edge_instructions_idx.at_put(edge, idx - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5857 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5858 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5859
a61af66fc99e Initial load
duke
parents:
diff changeset
5860
a61af66fc99e Initial load
duke
parents:
diff changeset
5861 bool EdgeMoveOptimizer::operations_different(LIR_Op* op1, LIR_Op* op2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5862 if (op1 == NULL || op2 == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5863 // at least one block is already empty -> no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5864 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5866
a61af66fc99e Initial load
duke
parents:
diff changeset
5867 if (op1->code() == lir_move && op2->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5868 assert(op1->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5869 assert(op2->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5870 LIR_Op1* move1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5871 LIR_Op1* move2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5872 if (move1->info() == move2->info() && move1->in_opr() == move2->in_opr() && move1->result_opr() == move2->result_opr()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5873 // these moves are exactly equal and can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5874 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5876
a61af66fc99e Initial load
duke
parents:
diff changeset
5877 } else if (op1->code() == lir_fxch && op2->code() == lir_fxch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5878 assert(op1->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5879 assert(op2->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5880 LIR_Op1* fxch1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5881 LIR_Op1* fxch2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5882 if (fxch1->in_opr()->as_jint() == fxch2->in_opr()->as_jint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5883 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5884 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5886
a61af66fc99e Initial load
duke
parents:
diff changeset
5887 } else if (op1->code() == lir_fpop_raw && op2->code() == lir_fpop_raw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5888 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5889 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5890 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5891
a61af66fc99e Initial load
duke
parents:
diff changeset
5892 // no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5893 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5894 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5895
a61af66fc99e Initial load
duke
parents:
diff changeset
5896 void EdgeMoveOptimizer::optimize_moves_at_block_end(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5897 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
5898
a61af66fc99e Initial load
duke
parents:
diff changeset
5899 if (block->is_predecessor(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5900 // currently we can't handle this correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
5901 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5903
a61af66fc99e Initial load
duke
parents:
diff changeset
5904 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5905 int num_preds = block->number_of_preds();
a61af66fc99e Initial load
duke
parents:
diff changeset
5906 assert(num_preds > 1, "do not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5907 assert(!block->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5908
a61af66fc99e Initial load
duke
parents:
diff changeset
5909 // setup a list with the lir-instructions of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5910 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5911 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5912 BlockBegin* pred = block->pred_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5913 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5914
a61af66fc99e Initial load
duke
parents:
diff changeset
5915 if (pred->number_of_sux() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5916 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
5917 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
5918 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5919 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5920
a61af66fc99e Initial load
duke
parents:
diff changeset
5921 assert(pred->number_of_sux() == 1, "can handle only one successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
5922 assert(pred->sux_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
5923 assert(pred_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5924 assert(pred_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5925 assert(pred_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5926
a61af66fc99e Initial load
duke
parents:
diff changeset
5927 if (pred_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5928 // can not optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5929 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5930 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5931
a61af66fc99e Initial load
duke
parents:
diff changeset
5932 // ignore the unconditional branch at the end of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
5933 append_instructions(pred_instructions, pred_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5934 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5935
a61af66fc99e Initial load
duke
parents:
diff changeset
5936
a61af66fc99e Initial load
duke
parents:
diff changeset
5937 // process lir-instructions while all predecessors end with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
5938 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5939 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
5940 for (i = 1; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5941 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5942 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
5943 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5944 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5945 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5946 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5947
a61af66fc99e Initial load
duke
parents:
diff changeset
5948 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
5949
a61af66fc99e Initial load
duke
parents:
diff changeset
5950 // insert the instruction at the beginning of the current block
a61af66fc99e Initial load
duke
parents:
diff changeset
5951 block->lir()->insert_before(1, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
5952
a61af66fc99e Initial load
duke
parents:
diff changeset
5953 // delete the instruction at the end of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5954 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5955 remove_cur_instruction(i, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5956 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5958 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5959
a61af66fc99e Initial load
duke
parents:
diff changeset
5960
a61af66fc99e Initial load
duke
parents:
diff changeset
5961 void EdgeMoveOptimizer::optimize_moves_at_block_begin(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5962 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
5963
a61af66fc99e Initial load
duke
parents:
diff changeset
5964 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5965 int num_sux = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
5966
a61af66fc99e Initial load
duke
parents:
diff changeset
5967 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5968
a61af66fc99e Initial load
duke
parents:
diff changeset
5969 assert(num_sux == 2, "method should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5970 assert(cur_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5971 assert(cur_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5972 assert(cur_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5973
a61af66fc99e Initial load
duke
parents:
diff changeset
5974 if (cur_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5975 // can no optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5976 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5977 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5978
a61af66fc99e Initial load
duke
parents:
diff changeset
5979 LIR_Op* branch = cur_instructions->at(cur_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5980 if (branch->info() != NULL || (branch->code() != lir_branch && branch->code() != lir_cond_float_branch)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5981 // not a valid case for optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5982 // currently, only blocks that end with two branches (conditional branch followed
a61af66fc99e Initial load
duke
parents:
diff changeset
5983 // by unconditional branch) are optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5984 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5985 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5986
a61af66fc99e Initial load
duke
parents:
diff changeset
5987 // now it is guaranteed that the block ends with two branch instructions.
a61af66fc99e Initial load
duke
parents:
diff changeset
5988 // the instructions are inserted at the end of the block before these two branches
a61af66fc99e Initial load
duke
parents:
diff changeset
5989 int insert_idx = cur_instructions->length() - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5990
a61af66fc99e Initial load
duke
parents:
diff changeset
5991 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5992 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
5993 for (i = insert_idx - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5994 LIR_Op* op = cur_instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5995 if ((op->code() == lir_branch || op->code() == lir_cond_float_branch) && ((LIR_OpBranch*)op)->block() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5996 assert(false, "block with two successors can have only two branch instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
5997 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5998 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5999 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6000
a61af66fc99e Initial load
duke
parents:
diff changeset
6001 // setup a list with the lir-instructions of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
6002 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6003 BlockBegin* sux = block->sux_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6004 LIR_OpList* sux_instructions = sux->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6005
a61af66fc99e Initial load
duke
parents:
diff changeset
6006 assert(sux_instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6007
a61af66fc99e Initial load
duke
parents:
diff changeset
6008 if (sux->number_of_preds() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6009 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
6010 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
6011 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
6012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6013 assert(sux->pred_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
6014 assert(!sux->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
6015
a61af66fc99e Initial load
duke
parents:
diff changeset
6016 // ignore the label at the beginning of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
6017 append_instructions(sux_instructions, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6018 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6019
a61af66fc99e Initial load
duke
parents:
diff changeset
6020 // process lir-instructions while all successors begin with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6021 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6022 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6023 for (i = 1; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6024 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6025 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
6026 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
6027 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
6028 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6030
a61af66fc99e Initial load
duke
parents:
diff changeset
6031 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
6032
a61af66fc99e Initial load
duke
parents:
diff changeset
6033 // insert instruction at end of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
6034 block->lir()->insert_before(insert_idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
6035 insert_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6036
a61af66fc99e Initial load
duke
parents:
diff changeset
6037 // delete the instructions at the beginning of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
6038 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6039 remove_cur_instruction(i, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
6040 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6041 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6042 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6043
a61af66fc99e Initial load
duke
parents:
diff changeset
6044
a61af66fc99e Initial load
duke
parents:
diff changeset
6045 // Implementation of ControlFlowOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
6046
a61af66fc99e Initial load
duke
parents:
diff changeset
6047 ControlFlowOptimizer::ControlFlowOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
6048 _original_preds(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
6049 {
a61af66fc99e Initial load
duke
parents:
diff changeset
6050 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6051
a61af66fc99e Initial load
duke
parents:
diff changeset
6052 void ControlFlowOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6053 ControlFlowOptimizer optimizer = ControlFlowOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
6054
a61af66fc99e Initial load
duke
parents:
diff changeset
6055 // push the OSR entry block to the end so that we're not jumping over it.
a61af66fc99e Initial load
duke
parents:
diff changeset
6056 BlockBegin* osr_entry = code->at(0)->end()->as_Base()->osr_entry();
a61af66fc99e Initial load
duke
parents:
diff changeset
6057 if (osr_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6058 int index = osr_entry->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
6059 assert(code->at(index) == osr_entry, "wrong index");
a61af66fc99e Initial load
duke
parents:
diff changeset
6060 code->remove_at(index);
a61af66fc99e Initial load
duke
parents:
diff changeset
6061 code->append(osr_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
6062 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6063
a61af66fc99e Initial load
duke
parents:
diff changeset
6064 optimizer.reorder_short_loops(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6065 optimizer.delete_empty_blocks(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6066 optimizer.delete_unnecessary_jumps(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6067 optimizer.delete_jumps_to_return(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6068 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6069
a61af66fc99e Initial load
duke
parents:
diff changeset
6070 void ControlFlowOptimizer::reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6071 int i = header_idx + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6072 int max_end = MIN2(header_idx + ShortLoopSize, code->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
6073 while (i < max_end && code->at(i)->loop_depth() >= header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6074 i++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6075 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6076
a61af66fc99e Initial load
duke
parents:
diff changeset
6077 if (i == code->length() || code->at(i)->loop_depth() < header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6078 int end_idx = i - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6079 BlockBegin* end_block = code->at(end_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
6080
a61af66fc99e Initial load
duke
parents:
diff changeset
6081 if (end_block->number_of_sux() == 1 && end_block->sux_at(0) == header_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6082 // short loop from header_idx to end_idx found -> reorder blocks such that
a61af66fc99e Initial load
duke
parents:
diff changeset
6083 // the header_block is the last block instead of the first block of the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
6084 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
6085 end_idx - header_idx + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
6086 header_block->block_id(), end_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6087
a61af66fc99e Initial load
duke
parents:
diff changeset
6088 for (int j = header_idx; j < end_idx; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6089 code->at_put(j, code->at(j + 1));
a61af66fc99e Initial load
duke
parents:
diff changeset
6090 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6091 code->at_put(end_idx, header_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6092
a61af66fc99e Initial load
duke
parents:
diff changeset
6093 // correct the flags so that any loop alignment occurs in the right place.
a61af66fc99e Initial load
duke
parents:
diff changeset
6094 assert(code->at(end_idx)->is_set(BlockBegin::backward_branch_target_flag), "must be backward branch target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6095 code->at(end_idx)->clear(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6096 code->at(header_idx)->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6097 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6098 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6099 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6100
a61af66fc99e Initial load
duke
parents:
diff changeset
6101 void ControlFlowOptimizer::reorder_short_loops(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6102 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6103 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6104
a61af66fc99e Initial load
duke
parents:
diff changeset
6105 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6106 reorder_short_loop(code, block, i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6109
a61af66fc99e Initial load
duke
parents:
diff changeset
6110 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6111 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6112
a61af66fc99e Initial load
duke
parents:
diff changeset
6113 // only blocks with exactly one successor can be deleted. Such blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6114 // must always end with an unconditional branch to this successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6115 bool ControlFlowOptimizer::can_delete_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6116 if (block->number_of_sux() != 1 || block->number_of_exception_handlers() != 0 || block->is_entry_block()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6117 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6119
a61af66fc99e Initial load
duke
parents:
diff changeset
6120 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6121
a61af66fc99e Initial load
duke
parents:
diff changeset
6122 assert(instructions->length() >= 2, "block must have label and branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6123 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6124 assert(instructions->last()->as_OpBranch() != NULL, "last instrcution must always be a branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6125 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "branch must be unconditional");
a61af66fc99e Initial load
duke
parents:
diff changeset
6126 assert(instructions->last()->as_OpBranch()->block() == block->sux_at(0), "branch target must be the successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
6127
a61af66fc99e Initial load
duke
parents:
diff changeset
6128 // block must have exactly one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6129
a61af66fc99e Initial load
duke
parents:
diff changeset
6130 if (instructions->length() == 2 && instructions->last()->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6131 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6133 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6135
a61af66fc99e Initial load
duke
parents:
diff changeset
6136 // substitute branch targets in all branch-instructions of this blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6137 void ControlFlowOptimizer::substitute_branch_target(BlockBegin* block, BlockBegin* target_from, BlockBegin* target_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6138 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
6139
a61af66fc99e Initial load
duke
parents:
diff changeset
6140 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6141
a61af66fc99e Initial load
duke
parents:
diff changeset
6142 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6143 for (int i = instructions->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6144 LIR_Op* op = instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6145
a61af66fc99e Initial load
duke
parents:
diff changeset
6146 if (op->code() == lir_branch || op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6147 assert(op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6148 LIR_OpBranch* branch = (LIR_OpBranch*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6149
a61af66fc99e Initial load
duke
parents:
diff changeset
6150 if (branch->block() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6151 branch->change_block(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6153 if (branch->ublock() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6154 branch->change_ublock(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6159
a61af66fc99e Initial load
duke
parents:
diff changeset
6160 void ControlFlowOptimizer::delete_empty_blocks(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6161 int old_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6162 int new_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6163 int num_blocks = code->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
6164
a61af66fc99e Initial load
duke
parents:
diff changeset
6165 while (old_pos < num_blocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6166 BlockBegin* block = code->at(old_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6167
a61af66fc99e Initial load
duke
parents:
diff changeset
6168 if (can_delete_block(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6169 BlockBegin* new_target = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6170
a61af66fc99e Initial load
duke
parents:
diff changeset
6171 // propagate backward branch target flag for correct code alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
6172 if (block->is_set(BlockBegin::backward_branch_target_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6173 new_target->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6174 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6175
a61af66fc99e Initial load
duke
parents:
diff changeset
6176 // collect a list with all predecessors that contains each predecessor only once
a61af66fc99e Initial load
duke
parents:
diff changeset
6177 // the predecessors of cur are changed during the substitution, so a copy of the
a61af66fc99e Initial load
duke
parents:
diff changeset
6178 // predecessor list is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6179 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6180 _original_preds.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6181 for (j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6182 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6183 if (_original_preds.index_of(pred) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6184 _original_preds.append(pred);
a61af66fc99e Initial load
duke
parents:
diff changeset
6185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6187
a61af66fc99e Initial load
duke
parents:
diff changeset
6188 for (j = _original_preds.length() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6189 BlockBegin* pred = _original_preds.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6190 substitute_branch_target(pred, block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6191 pred->substitute_sux(block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6192 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6193 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6194 // adjust position of this block in the block list if blocks before
a61af66fc99e Initial load
duke
parents:
diff changeset
6195 // have been deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6196 if (new_pos != old_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6197 code->at_put(new_pos, code->at(old_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
6198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6199 new_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6201 old_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6203 code->truncate(new_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6204
a61af66fc99e Initial load
duke
parents:
diff changeset
6205 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6207
a61af66fc99e Initial load
duke
parents:
diff changeset
6208 void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6209 // skip the last block because there a branch is always necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6210 for (int i = code->length() - 2; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6211 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6212 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6213
a61af66fc99e Initial load
duke
parents:
diff changeset
6214 LIR_Op* last_op = instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6215 if (last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6216 assert(last_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6217 LIR_OpBranch* last_branch = (LIR_OpBranch*)last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6218
a61af66fc99e Initial load
duke
parents:
diff changeset
6219 assert(last_branch->block() != NULL, "last branch must always have a block as target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6220 assert(last_branch->label() == last_branch->block()->label(), "must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
6221
a61af66fc99e Initial load
duke
parents:
diff changeset
6222 if (last_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6223 if (last_branch->block() == code->at(i + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6224
a61af66fc99e Initial load
duke
parents:
diff changeset
6225 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
6226
a61af66fc99e Initial load
duke
parents:
diff changeset
6227 // delete last branch instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6228 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6229
a61af66fc99e Initial load
duke
parents:
diff changeset
6230 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6231 LIR_Op* prev_op = instructions->at(instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6232 if (prev_op->code() == lir_branch || prev_op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6233 assert(prev_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6234 LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6235
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6236 if (prev_branch->stub() == NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6237
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6238 LIR_Op2* prev_cmp = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6239
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6240 for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6241 prev_op = instructions->at(j);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6242 if (prev_op->code() == lir_cmp) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6243 assert(prev_op->as_Op2() != NULL, "branch must be of type LIR_Op2");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6244 prev_cmp = (LIR_Op2*)prev_op;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6245 assert(prev_branch->cond() == prev_cmp->condition(), "should be the same");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6246 }
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6247 }
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6248 assert(prev_cmp != NULL, "should have found comp instruction for branch");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6249 if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6250
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6251 TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id()));
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6252
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6253 // eliminate a conditional branch to the immediate successor
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6254 prev_branch->change_block(last_branch->block());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6255 prev_branch->negate_cond();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6256 prev_cmp->set_condition(prev_branch->cond());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6257 instructions->truncate(instructions->length() - 1);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6258 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6259 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6265
a61af66fc99e Initial load
duke
parents:
diff changeset
6266 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6267 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6268
a61af66fc99e Initial load
duke
parents:
diff changeset
6269 void ControlFlowOptimizer::delete_jumps_to_return(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6270 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6271 BitMap return_converted(BlockBegin::number_of_blocks());
a61af66fc99e Initial load
duke
parents:
diff changeset
6272 return_converted.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6273 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6274
a61af66fc99e Initial load
duke
parents:
diff changeset
6275 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6276 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6277 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6278 LIR_Op* cur_last_op = cur_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6279
a61af66fc99e Initial load
duke
parents:
diff changeset
6280 assert(cur_instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6281 if (cur_instructions->length() == 2 && cur_last_op->code() == lir_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6282 // the block contains only a label and a return
a61af66fc99e Initial load
duke
parents:
diff changeset
6283 // if a predecessor ends with an unconditional jump to this block, then the jump
a61af66fc99e Initial load
duke
parents:
diff changeset
6284 // can be replaced with a return instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6285 //
a61af66fc99e Initial load
duke
parents:
diff changeset
6286 // Note: the original block with only a return statement cannot be deleted completely
a61af66fc99e Initial load
duke
parents:
diff changeset
6287 // because the predecessors might have other (conditional) jumps to this block
a61af66fc99e Initial load
duke
parents:
diff changeset
6288 // -> this may lead to unnecesary return instructions in the final code
a61af66fc99e Initial load
duke
parents:
diff changeset
6289
a61af66fc99e Initial load
duke
parents:
diff changeset
6290 assert(cur_last_op->info() == NULL, "return instructions do not have debug information");
a61af66fc99e Initial load
duke
parents:
diff changeset
6291 assert(block->number_of_sux() == 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
6292 (return_converted.at(block->block_id()) && block->number_of_sux() == 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
6293 "blocks that end with return must not have successors");
a61af66fc99e Initial load
duke
parents:
diff changeset
6294
a61af66fc99e Initial load
duke
parents:
diff changeset
6295 assert(cur_last_op->as_Op1() != NULL, "return must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
6296 LIR_Opr return_opr = ((LIR_Op1*)cur_last_op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6297
a61af66fc99e Initial load
duke
parents:
diff changeset
6298 for (int j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6299 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6300 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6301 LIR_Op* pred_last_op = pred_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6302
a61af66fc99e Initial load
duke
parents:
diff changeset
6303 if (pred_last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6304 assert(pred_last_op->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6305 LIR_OpBranch* pred_last_branch = (LIR_OpBranch*)pred_last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6306
a61af66fc99e Initial load
duke
parents:
diff changeset
6307 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
6308 // replace the jump to a return with a direct return
a61af66fc99e Initial load
duke
parents:
diff changeset
6309 // Note: currently the edge between the blocks is not deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6310 pred_instructions->at_put(pred_instructions->length() - 1, new LIR_Op1(lir_return, return_opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
6311 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6312 return_converted.set_bit(pred->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
6313 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6315 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6316 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6318 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6320
a61af66fc99e Initial load
duke
parents:
diff changeset
6321
a61af66fc99e Initial load
duke
parents:
diff changeset
6322 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6323 void ControlFlowOptimizer::verify(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6324 for (int i = 0; i < code->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6325 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6326 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6327
a61af66fc99e Initial load
duke
parents:
diff changeset
6328 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6329 for (j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6330 LIR_OpBranch* op_branch = instructions->at(j)->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6331
a61af66fc99e Initial load
duke
parents:
diff changeset
6332 if (op_branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6333 assert(op_branch->block() == NULL || code->index_of(op_branch->block()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6334 assert(op_branch->ublock() == NULL || code->index_of(op_branch->ublock()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6335 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6336 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6337
a61af66fc99e Initial load
duke
parents:
diff changeset
6338 for (j = 0; j < block->number_of_sux() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6339 BlockBegin* sux = block->sux_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6340 assert(code->index_of(sux) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6342
a61af66fc99e Initial load
duke
parents:
diff changeset
6343 for (j = 0; j < block->number_of_preds() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6344 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6345 assert(code->index_of(pred) != -1, "successor not valid");
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 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6350
a61af66fc99e Initial load
duke
parents:
diff changeset
6351
a61af66fc99e Initial load
duke
parents:
diff changeset
6352 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
6353
a61af66fc99e Initial load
duke
parents:
diff changeset
6354 // Implementation of LinearStatistic
a61af66fc99e Initial load
duke
parents:
diff changeset
6355
a61af66fc99e Initial load
duke
parents:
diff changeset
6356 const char* LinearScanStatistic::counter_name(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6357 switch (counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6358 case counter_method: return "compiled methods";
a61af66fc99e Initial load
duke
parents:
diff changeset
6359 case counter_fpu_method: return "methods using fpu";
a61af66fc99e Initial load
duke
parents:
diff changeset
6360 case counter_loop_method: return "methods with loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6361 case counter_exception_method:return "methods with xhandler";
a61af66fc99e Initial load
duke
parents:
diff changeset
6362
a61af66fc99e Initial load
duke
parents:
diff changeset
6363 case counter_loop: return "loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6364 case counter_block: return "blocks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6365 case counter_loop_block: return "blocks inside loop";
a61af66fc99e Initial load
duke
parents:
diff changeset
6366 case counter_exception_block: return "exception handler entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6367 case counter_interval: return "intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6368 case counter_fixed_interval: return "fixed intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6369 case counter_range: return "ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6370 case counter_fixed_range: return "fixed ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6371 case counter_use_pos: return "use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6372 case counter_fixed_use_pos: return "fixed use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6373 case counter_spill_slots: return "spill slots";
a61af66fc99e Initial load
duke
parents:
diff changeset
6374
a61af66fc99e Initial load
duke
parents:
diff changeset
6375 // counter for classes of lir instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
6376 case counter_instruction: return "total instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6377 case counter_label: return "labels";
a61af66fc99e Initial load
duke
parents:
diff changeset
6378 case counter_entry: return "method entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6379 case counter_return: return "method returns";
a61af66fc99e Initial load
duke
parents:
diff changeset
6380 case counter_call: return "method calls";
a61af66fc99e Initial load
duke
parents:
diff changeset
6381 case counter_move: return "moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6382 case counter_cmp: return "compare";
a61af66fc99e Initial load
duke
parents:
diff changeset
6383 case counter_cond_branch: return "conditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6384 case counter_uncond_branch: return "unconditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6385 case counter_stub_branch: return "branches to stub";
a61af66fc99e Initial load
duke
parents:
diff changeset
6386 case counter_alu: return "artithmetic + logic";
a61af66fc99e Initial load
duke
parents:
diff changeset
6387 case counter_alloc: return "allocations";
a61af66fc99e Initial load
duke
parents:
diff changeset
6388 case counter_sync: return "synchronisation";
a61af66fc99e Initial load
duke
parents:
diff changeset
6389 case counter_throw: return "throw";
a61af66fc99e Initial load
duke
parents:
diff changeset
6390 case counter_unwind: return "unwind";
a61af66fc99e Initial load
duke
parents:
diff changeset
6391 case counter_typecheck: return "type+null-checks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6392 case counter_fpu_stack: return "fpu-stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6393 case counter_misc_inst: return "other instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6394 case counter_other_inst: return "misc. instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6395
a61af66fc99e Initial load
duke
parents:
diff changeset
6396 // counter for different types of moves
a61af66fc99e Initial load
duke
parents:
diff changeset
6397 case counter_move_total: return "total moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6398 case counter_move_reg_reg: return "register->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6399 case counter_move_reg_stack: return "register->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6400 case counter_move_stack_reg: return "stack->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6401 case counter_move_stack_stack:return "stack->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6402 case counter_move_reg_mem: return "register->memory";
a61af66fc99e Initial load
duke
parents:
diff changeset
6403 case counter_move_mem_reg: return "memory->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6404 case counter_move_const_any: return "constant->any";
a61af66fc99e Initial load
duke
parents:
diff changeset
6405
a61af66fc99e Initial load
duke
parents:
diff changeset
6406 case blank_line_1: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6407 case blank_line_2: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6408
a61af66fc99e Initial load
duke
parents:
diff changeset
6409 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6410 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6411 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6412
a61af66fc99e Initial load
duke
parents:
diff changeset
6413 LinearScanStatistic::Counter LinearScanStatistic::base_counter(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6414 if (counter_idx == counter_fpu_method || counter_idx == counter_loop_method || counter_idx == counter_exception_method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6415 return counter_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
6416 } else if (counter_idx == counter_loop_block || counter_idx == counter_exception_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6417 return counter_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
6418 } else if (counter_idx >= counter_instruction && counter_idx <= counter_other_inst) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6419 return counter_instruction;
a61af66fc99e Initial load
duke
parents:
diff changeset
6420 } else if (counter_idx >= counter_move_total && counter_idx <= counter_move_const_any) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6421 return counter_move_total;
a61af66fc99e Initial load
duke
parents:
diff changeset
6422 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6423 return invalid_counter;
a61af66fc99e Initial load
duke
parents:
diff changeset
6424 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6425
a61af66fc99e Initial load
duke
parents:
diff changeset
6426 LinearScanStatistic::LinearScanStatistic() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6427 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6428 _counters_sum[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6429 _counters_max[i] = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6431
a61af66fc99e Initial load
duke
parents:
diff changeset
6432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6433
a61af66fc99e Initial load
duke
parents:
diff changeset
6434 // add the method-local numbers to the total sum
a61af66fc99e Initial load
duke
parents:
diff changeset
6435 void LinearScanStatistic::sum_up(LinearScanStatistic &method_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6436 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6437 _counters_sum[i] += method_statistic._counters_sum[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
6438 _counters_max[i] = MAX2(_counters_max[i], method_statistic._counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6441
a61af66fc99e Initial load
duke
parents:
diff changeset
6442 void LinearScanStatistic::print(const char* title) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6443 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6444 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6445 tty->print_cr("***** LinearScan statistic - %s *****", title);
a61af66fc99e Initial load
duke
parents:
diff changeset
6446
a61af66fc99e Initial load
duke
parents:
diff changeset
6447 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6448 if (_counters_sum[i] > 0 || _counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6449 tty->print("%25s: %8d", counter_name(i), _counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6450
a61af66fc99e Initial load
duke
parents:
diff changeset
6451 if (base_counter(i) != invalid_counter) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6452 tty->print(" (%5.1f%%) ", _counters_sum[i] * 100.0 / _counters_sum[base_counter(i)]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6453 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6454 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
6455 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6456
a61af66fc99e Initial load
duke
parents:
diff changeset
6457 if (_counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6458 tty->print("%8d", _counters_max[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6461 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6462 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6464 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6465
a61af66fc99e Initial load
duke
parents:
diff changeset
6466 void LinearScanStatistic::collect(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6467 inc_counter(counter_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6468 if (allocator->has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6469 inc_counter(counter_fpu_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6471 if (allocator->num_loops() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6472 inc_counter(counter_loop_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6474 inc_counter(counter_loop, allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6475 inc_counter(counter_spill_slots, allocator->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
6476
a61af66fc99e Initial load
duke
parents:
diff changeset
6477 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
6478 for (i = 0; i < allocator->interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6479 Interval* cur = allocator->interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6480
a61af66fc99e Initial load
duke
parents:
diff changeset
6481 if (cur != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6482 inc_counter(counter_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6483 inc_counter(counter_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6484 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6485 inc_counter(counter_fixed_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6486 inc_counter(counter_fixed_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6488
a61af66fc99e Initial load
duke
parents:
diff changeset
6489 Range* range = cur->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
6490 while (range != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6491 inc_counter(counter_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6492 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6493 inc_counter(counter_fixed_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6494 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6495 range = range->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
6496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6499
a61af66fc99e Initial load
duke
parents:
diff changeset
6500 bool has_xhandlers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6501 // Note: only count blocks that are in code-emit order
a61af66fc99e Initial load
duke
parents:
diff changeset
6502 for (i = 0; i < allocator->ir()->code()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6503 BlockBegin* cur = allocator->ir()->code()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6504
a61af66fc99e Initial load
duke
parents:
diff changeset
6505 inc_counter(counter_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6506 if (cur->loop_depth() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6507 inc_counter(counter_loop_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6508 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6509 if (cur->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6510 inc_counter(counter_exception_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6511 has_xhandlers = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6513
a61af66fc99e Initial load
duke
parents:
diff changeset
6514 LIR_OpList* instructions = cur->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6515 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6516 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6517
a61af66fc99e Initial load
duke
parents:
diff changeset
6518 inc_counter(counter_instruction);
a61af66fc99e Initial load
duke
parents:
diff changeset
6519
a61af66fc99e Initial load
duke
parents:
diff changeset
6520 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6521 case lir_label: inc_counter(counter_label); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6522 case lir_std_entry:
a61af66fc99e Initial load
duke
parents:
diff changeset
6523 case lir_osr_entry: inc_counter(counter_entry); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6524 case lir_return: inc_counter(counter_return); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6525
a61af66fc99e Initial load
duke
parents:
diff changeset
6526 case lir_rtcall:
a61af66fc99e Initial load
duke
parents:
diff changeset
6527 case lir_static_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6528 case lir_optvirtual_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6529 case lir_virtual_call: inc_counter(counter_call); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6530
a61af66fc99e Initial load
duke
parents:
diff changeset
6531 case lir_move: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6532 inc_counter(counter_move);
a61af66fc99e Initial load
duke
parents:
diff changeset
6533 inc_counter(counter_move_total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6534
a61af66fc99e Initial load
duke
parents:
diff changeset
6535 LIR_Opr in = op->as_Op1()->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6536 LIR_Opr res = op->as_Op1()->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6537 if (in->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6538 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6539 inc_counter(counter_move_reg_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6540 } else if (res->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6541 inc_counter(counter_move_reg_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6542 } else if (res->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6543 inc_counter(counter_move_reg_mem);
a61af66fc99e Initial load
duke
parents:
diff changeset
6544 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6545 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6546 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6547 } else if (in->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6548 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6549 inc_counter(counter_move_stack_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6550 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6551 inc_counter(counter_move_stack_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6553 } else if (in->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6554 assert(res->is_register(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
6555 inc_counter(counter_move_mem_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6556 } else if (in->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6557 inc_counter(counter_move_const_any);
a61af66fc99e Initial load
duke
parents:
diff changeset
6558 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6559 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6560 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6561 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6563
a61af66fc99e Initial load
duke
parents:
diff changeset
6564 case lir_cmp: inc_counter(counter_cmp); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6565
a61af66fc99e Initial load
duke
parents:
diff changeset
6566 case lir_branch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6567 case lir_cond_float_branch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6568 LIR_OpBranch* branch = op->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6569 if (branch->block() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6570 inc_counter(counter_stub_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6571 } else if (branch->cond() == lir_cond_always) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6572 inc_counter(counter_uncond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6573 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6574 inc_counter(counter_cond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6576 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6578
a61af66fc99e Initial load
duke
parents:
diff changeset
6579 case lir_neg:
a61af66fc99e Initial load
duke
parents:
diff changeset
6580 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
6581 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
6582 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
6583 case lir_mul_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6584 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
6585 case lir_div_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6586 case lir_rem:
a61af66fc99e Initial load
duke
parents:
diff changeset
6587 case lir_sqrt:
a61af66fc99e Initial load
duke
parents:
diff changeset
6588 case lir_sin:
a61af66fc99e Initial load
duke
parents:
diff changeset
6589 case lir_cos:
a61af66fc99e Initial load
duke
parents:
diff changeset
6590 case lir_abs:
a61af66fc99e Initial load
duke
parents:
diff changeset
6591 case lir_log10:
a61af66fc99e Initial load
duke
parents:
diff changeset
6592 case lir_log:
6084
6759698e3140 7133857: exp() and pow() should use the x87 ISA on x86
roland
parents: 5906
diff changeset
6593 case lir_pow:
6759698e3140 7133857: exp() and pow() should use the x87 ISA on x86
roland
parents: 5906
diff changeset
6594 case lir_exp:
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6595 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
6596 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
6597 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
6598 case lir_shl:
a61af66fc99e Initial load
duke
parents:
diff changeset
6599 case lir_shr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6600 case lir_ushr: inc_counter(counter_alu); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6601
a61af66fc99e Initial load
duke
parents:
diff changeset
6602 case lir_alloc_object:
a61af66fc99e Initial load
duke
parents:
diff changeset
6603 case lir_alloc_array: inc_counter(counter_alloc); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6604
a61af66fc99e Initial load
duke
parents:
diff changeset
6605 case lir_monaddr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6606 case lir_lock:
a61af66fc99e Initial load
duke
parents:
diff changeset
6607 case lir_unlock: inc_counter(counter_sync); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6608
a61af66fc99e Initial load
duke
parents:
diff changeset
6609 case lir_throw: inc_counter(counter_throw); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6610
a61af66fc99e Initial load
duke
parents:
diff changeset
6611 case lir_unwind: inc_counter(counter_unwind); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6612
a61af66fc99e Initial load
duke
parents:
diff changeset
6613 case lir_null_check:
a61af66fc99e Initial load
duke
parents:
diff changeset
6614 case lir_leal:
a61af66fc99e Initial load
duke
parents:
diff changeset
6615 case lir_instanceof:
a61af66fc99e Initial load
duke
parents:
diff changeset
6616 case lir_checkcast:
a61af66fc99e Initial load
duke
parents:
diff changeset
6617 case lir_store_check: inc_counter(counter_typecheck); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6618
a61af66fc99e Initial load
duke
parents:
diff changeset
6619 case lir_fpop_raw:
a61af66fc99e Initial load
duke
parents:
diff changeset
6620 case lir_fxch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6621 case lir_fld: inc_counter(counter_fpu_stack); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6622
a61af66fc99e Initial load
duke
parents:
diff changeset
6623 case lir_nop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6624 case lir_push:
a61af66fc99e Initial load
duke
parents:
diff changeset
6625 case lir_pop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6626 case lir_convert:
a61af66fc99e Initial load
duke
parents:
diff changeset
6627 case lir_roundfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6628 case lir_cmove: inc_counter(counter_misc_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6629
a61af66fc99e Initial load
duke
parents:
diff changeset
6630 default: inc_counter(counter_other_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6632 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6634
a61af66fc99e Initial load
duke
parents:
diff changeset
6635 if (has_xhandlers) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6636 inc_counter(counter_exception_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6637 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6638 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6639
a61af66fc99e Initial load
duke
parents:
diff changeset
6640 void LinearScanStatistic::compute(LinearScan* allocator, LinearScanStatistic &global_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6641 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6642
a61af66fc99e Initial load
duke
parents:
diff changeset
6643 LinearScanStatistic local_statistic = LinearScanStatistic();
a61af66fc99e Initial load
duke
parents:
diff changeset
6644
a61af66fc99e Initial load
duke
parents:
diff changeset
6645 local_statistic.collect(allocator);
a61af66fc99e Initial load
duke
parents:
diff changeset
6646 global_statistic.sum_up(local_statistic);
a61af66fc99e Initial load
duke
parents:
diff changeset
6647
a61af66fc99e Initial load
duke
parents:
diff changeset
6648 if (TraceLinearScanLevel > 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6649 local_statistic.print("current local statistic");
a61af66fc99e Initial load
duke
parents:
diff changeset
6650 }
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 // Implementation of LinearTimers
a61af66fc99e Initial load
duke
parents:
diff changeset
6656
a61af66fc99e Initial load
duke
parents:
diff changeset
6657 LinearScanTimers::LinearScanTimers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6658 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6659 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6660 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6661 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6662
a61af66fc99e Initial load
duke
parents:
diff changeset
6663 const char* LinearScanTimers::timer_name(int idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6664 switch (idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6665 case timer_do_nothing: return "Nothing (Time Check)";
a61af66fc99e Initial load
duke
parents:
diff changeset
6666 case timer_number_instructions: return "Number Instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6667 case timer_compute_local_live_sets: return "Local Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6668 case timer_compute_global_live_sets: return "Global Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6669 case timer_build_intervals: return "Build Intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6670 case timer_sort_intervals_before: return "Sort Intervals Before";
a61af66fc99e Initial load
duke
parents:
diff changeset
6671 case timer_allocate_registers: return "Allocate Registers";
a61af66fc99e Initial load
duke
parents:
diff changeset
6672 case timer_resolve_data_flow: return "Resolve Data Flow";
a61af66fc99e Initial load
duke
parents:
diff changeset
6673 case timer_sort_intervals_after: return "Sort Intervals After";
a61af66fc99e Initial load
duke
parents:
diff changeset
6674 case timer_eliminate_spill_moves: return "Spill optimization";
a61af66fc99e Initial load
duke
parents:
diff changeset
6675 case timer_assign_reg_num: return "Assign Reg Num";
a61af66fc99e Initial load
duke
parents:
diff changeset
6676 case timer_allocate_fpu_stack: return "Allocate FPU Stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6677 case timer_optimize_lir: return "Optimize LIR";
a61af66fc99e Initial load
duke
parents:
diff changeset
6678 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6679 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6680 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6681
a61af66fc99e Initial load
duke
parents:
diff changeset
6682 void LinearScanTimers::begin_method() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6683 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6684 // reset all timers to measure only current method
a61af66fc99e Initial load
duke
parents:
diff changeset
6685 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6686 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6687 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6688 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6689 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6690
a61af66fc99e Initial load
duke
parents:
diff changeset
6691 void LinearScanTimers::end_method(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6692 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6693
a61af66fc99e Initial load
duke
parents:
diff changeset
6694 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6695 double total = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6696 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6697 total += timer(i)->seconds() - c;
a61af66fc99e Initial load
duke
parents:
diff changeset
6698 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6699
a61af66fc99e Initial load
duke
parents:
diff changeset
6700 if (total >= 0.0005) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6701 // print all information in one line for automatic processing
a61af66fc99e Initial load
duke
parents:
diff changeset
6702 tty->print("@"); allocator->compilation()->method()->print_name();
a61af66fc99e Initial load
duke
parents:
diff changeset
6703
a61af66fc99e Initial load
duke
parents:
diff changeset
6704 tty->print("@ %d ", allocator->compilation()->method()->code_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
6705 tty->print("@ %d ", allocator->block_at(allocator->block_count() - 1)->last_lir_instruction_id() / 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6706 tty->print("@ %d ", allocator->block_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6707 tty->print("@ %d ", allocator->num_virtual_regs());
a61af66fc99e Initial load
duke
parents:
diff changeset
6708 tty->print("@ %d ", allocator->interval_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6709 tty->print("@ %d ", allocator->_num_calls);
a61af66fc99e Initial load
duke
parents:
diff changeset
6710 tty->print("@ %d ", allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6711
a61af66fc99e Initial load
duke
parents:
diff changeset
6712 tty->print("@ %6.6f ", total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6713 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6714 tty->print("@ %4.1f ", ((timer(i)->seconds() - c) / total) * 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
6715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6716 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6719 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6720
a61af66fc99e Initial load
duke
parents:
diff changeset
6721 void LinearScanTimers::print(double total_time) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6722 if (TimeLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6723 // correction value: sum of dummy-timer that only measures the time that
a61af66fc99e Initial load
duke
parents:
diff changeset
6724 // is necesary to start and stop itself
a61af66fc99e Initial load
duke
parents:
diff changeset
6725 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6726
a61af66fc99e Initial load
duke
parents:
diff changeset
6727 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6728 double t = timer(i)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6729 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
6730 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6731 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6732 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6733
a61af66fc99e Initial load
duke
parents:
diff changeset
6734 #endif // #ifndef PRODUCT