annotate src/share/vm/c1/c1_LinearScan.cpp @ 20543:e7d0505c8a30

8059758: Footprint regressions with JDK-8038423 Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything. Reviewed-by: jwilhelm, brutisso
author tschatzl
date Fri, 10 Oct 2014 15:51:58 +0200
parents d04cb4166be7
children 7848fc12602b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
17467
55fb97c4c58d 8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents: 13044
diff changeset
2 * Copyright (c) 2005, 2013, 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 // allocate cpu registers
20244
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1632 create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals,
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1633 is_precolored_cpu_interval, is_virtual_cpu_interval);
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1634
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1635 // allocate fpu registers
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1636 create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals,
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1637 is_precolored_fpu_interval, is_virtual_fpu_interval);
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1638
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1639 // the fpu interval allocation cannot be moved down below with the fpu section as
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1640 // the cpu_lsw.walk() changes interval positions.
d04cb4166be7 8040921: Uninitialised memory in hotspot/src/share/vm/c1/c1_LinearScan.cpp
morris
parents: 17980
diff changeset
1641
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 cpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 cpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1645
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1647 LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 fpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 fpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1652
a61af66fc99e Initial load
duke
parents:
diff changeset
1653
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 // ********** Phase 6: resolve data flow
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 // (insert moves at edges between blocks if intervals have been split)
a61af66fc99e Initial load
duke
parents:
diff changeset
1656
a61af66fc99e Initial load
duke
parents:
diff changeset
1657 // wrapper for Interval::split_child_at_op_id that performs a bailout in product mode
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 // instead of returning NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
1659 Interval* LinearScan::split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1660 Interval* result = interval->split_child_at_op_id(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1661 if (result != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
1663 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1664
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 assert(false, "must find an interval, but do a clean bailout in product mode");
a61af66fc99e Initial load
duke
parents:
diff changeset
1666 result = new Interval(LIR_OprDesc::vreg_base);
a61af66fc99e Initial load
duke
parents:
diff changeset
1667 result->assign_reg(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 result->set_type(T_INT);
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 BAILOUT_("LinearScan: interval is NULL", result);
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1671
a61af66fc99e Initial load
duke
parents:
diff changeset
1672
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 Interval* LinearScan::interval_at_block_begin(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1674 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1676
a61af66fc99e Initial load
duke
parents:
diff changeset
1677 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
1678 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1679
a61af66fc99e Initial load
duke
parents:
diff changeset
1680 Interval* LinearScan::interval_at_block_end(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1681 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1683
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 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
1685 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1686
a61af66fc99e Initial load
duke
parents:
diff changeset
1687 Interval* LinearScan::interval_at_op_id(int reg_num, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1688 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1689 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1690
a61af66fc99e Initial load
duke
parents:
diff changeset
1691 return split_child_at_op_id(interval_at(reg_num), op_id, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1693
a61af66fc99e Initial load
duke
parents:
diff changeset
1694
a61af66fc99e Initial load
duke
parents:
diff changeset
1695 void LinearScan::resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1696 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1697
a61af66fc99e Initial load
duke
parents:
diff changeset
1698 const int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 const int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1700 const BitMap live_at_edge = to_block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
1701
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 // 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
1703 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
1704 assert(r < num_regs, "live information set for not exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1705 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
1706
a61af66fc99e Initial load
duke
parents:
diff changeset
1707 Interval* from_interval = interval_at_block_end(from_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1708 Interval* to_interval = interval_at_block_begin(to_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1709
a61af66fc99e Initial load
duke
parents:
diff changeset
1710 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
1711 // need to insert move instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1712 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1713 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1714 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1716
a61af66fc99e Initial load
duke
parents:
diff changeset
1717
a61af66fc99e Initial load
duke
parents:
diff changeset
1718 void LinearScan::resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1719 if (from_block->number_of_sux() <= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1720 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
1721
a61af66fc99e Initial load
duke
parents:
diff changeset
1722 LIR_OpList* instructions = from_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1723 LIR_OpBranch* branch = instructions->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
1724 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 // insert moves before branch
a61af66fc99e Initial load
duke
parents:
diff changeset
1726 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
1727 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1728 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1729 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1730 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1731
a61af66fc99e Initial load
duke
parents:
diff changeset
1732 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1733 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
1734 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1735 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
1736
a61af66fc99e Initial load
duke
parents:
diff changeset
1737 // because the number of predecessor edges matches the number of
a61af66fc99e Initial load
duke
parents:
diff changeset
1738 // successor edges, blocks which are reached by switch statements
a61af66fc99e Initial load
duke
parents:
diff changeset
1739 // may have be more than one predecessor but it will be guaranteed
a61af66fc99e Initial load
duke
parents:
diff changeset
1740 // that all predecessors will be the same.
a61af66fc99e Initial load
duke
parents:
diff changeset
1741 for (int i = 0; i < to_block->number_of_preds(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 assert(from_block == to_block->pred_at(i), "all critical edges must be broken");
a61af66fc99e Initial load
duke
parents:
diff changeset
1743 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1745
a61af66fc99e Initial load
duke
parents:
diff changeset
1746 move_resolver.set_insert_position(to_block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1747 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1748 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1749
a61af66fc99e Initial load
duke
parents:
diff changeset
1750
a61af66fc99e Initial load
duke
parents:
diff changeset
1751 // insert necessary moves (spilling or reloading) at edges between blocks if interval has been split
a61af66fc99e Initial load
duke
parents:
diff changeset
1752 void LinearScan::resolve_data_flow() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1753 TIME_LINEAR_SCAN(timer_resolve_data_flow);
a61af66fc99e Initial load
duke
parents:
diff changeset
1754
a61af66fc99e Initial load
duke
parents:
diff changeset
1755 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1756 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1757 BitMap block_completed(num_blocks); block_completed.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1758 BitMap already_resolved(num_blocks); already_resolved.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1759
a61af66fc99e Initial load
duke
parents:
diff changeset
1760 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1761 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1762 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1763
a61af66fc99e Initial load
duke
parents:
diff changeset
1764 // check if block has only one predecessor and only one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
1765 if (block->number_of_preds() == 1 && block->number_of_sux() == 1 && block->number_of_exception_handlers() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1766 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1767 assert(instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1768 assert(instructions->last()->code() == lir_branch, "block with successors must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1769 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block with successor must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1770
a61af66fc99e Initial load
duke
parents:
diff changeset
1771 // check if block is empty (only label and branch)
a61af66fc99e Initial load
duke
parents:
diff changeset
1772 if (instructions->length() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1773 BlockBegin* pred = block->pred_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1774 BlockBegin* sux = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1775
a61af66fc99e Initial load
duke
parents:
diff changeset
1776 // prevent optimization of two consecutive blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1777 if (!block_completed.at(pred->linear_scan_number()) && !block_completed.at(sux->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1778 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
1779 block_completed.set_bit(block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1780
a61af66fc99e Initial load
duke
parents:
diff changeset
1781 // directly resolve between pred and sux (without looking at the empty block between)
a61af66fc99e Initial load
duke
parents:
diff changeset
1782 resolve_collect_mappings(pred, sux, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1783 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1784 move_resolver.set_insert_position(block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1785 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1786 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1787 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1788 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1789 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1790 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1791
a61af66fc99e Initial load
duke
parents:
diff changeset
1792
a61af66fc99e Initial load
duke
parents:
diff changeset
1793 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1794 if (!block_completed.at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1795 BlockBegin* from_block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1796 already_resolved.set_from(block_completed);
a61af66fc99e Initial load
duke
parents:
diff changeset
1797
a61af66fc99e Initial load
duke
parents:
diff changeset
1798 int num_sux = from_block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
1799 for (int s = 0; s < num_sux; s++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1800 BlockBegin* to_block = from_block->sux_at(s);
a61af66fc99e Initial load
duke
parents:
diff changeset
1801
a61af66fc99e Initial load
duke
parents:
diff changeset
1802 // check for duplicate edges between the same blocks (can happen with switch blocks)
a61af66fc99e Initial load
duke
parents:
diff changeset
1803 if (!already_resolved.at(to_block->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1804 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
1805 already_resolved.set_bit(to_block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1806
a61af66fc99e Initial load
duke
parents:
diff changeset
1807 // collect all intervals that have been split between from_block and to_block
a61af66fc99e Initial load
duke
parents:
diff changeset
1808 resolve_collect_mappings(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1809 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1810 resolve_find_insert_pos(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1811 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1812 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1818
a61af66fc99e Initial load
duke
parents:
diff changeset
1819
a61af66fc99e Initial load
duke
parents:
diff changeset
1820 void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1821 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1822 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1823 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1824 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1825
a61af66fc99e Initial load
duke
parents:
diff changeset
1826 Interval* interval = interval_at_block_begin(block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1827 int reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1828 int regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
1829
a61af66fc99e Initial load
duke
parents:
diff changeset
1830 if ((reg < nof_regs && interval->always_in_memory()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1831 (use_fpu_stack_allocation() && reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1832 // the interval is split to get a short range that is located on the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1833 // in the following two cases:
a61af66fc99e Initial load
duke
parents:
diff changeset
1834 // * the interval started in memory (e.g. method parameter), but is currently in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1835 // this is an optimization for exception handling that reduces the number of moves that
a61af66fc99e Initial load
duke
parents:
diff changeset
1836 // are necessary for resolving the states when an exception uses this exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1837 // * the interval would be on the fpu stack at the begin of the exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1838 // this is not allowed because of the complicated fpu stack handling on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1839
a61af66fc99e Initial load
duke
parents:
diff changeset
1840 // range that will be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
1841 int from_op_id = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1842 int to_op_id = from_op_id + 1; // short live range of length 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1843 assert(interval->from() <= from_op_id && interval->to() >= to_op_id,
a61af66fc99e Initial load
duke
parents:
diff changeset
1844 "no split allowed between exception entry and first instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
1845
a61af66fc99e Initial load
duke
parents:
diff changeset
1846 if (interval->from() != from_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1847 // the part before from_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1848 interval = interval->split(from_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1849 interval->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
1850 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
1851 } else {
7223744c2784 6579789: Internal error "c1_LinearScan.cpp:1429 Error: assert(false,"")" in debuggee with fastdebug VM
never
parents: 2002
diff changeset
1852 _needs_full_resort = true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1853 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1854 assert(interval->from() == from_op_id, "must be true now");
a61af66fc99e Initial load
duke
parents:
diff changeset
1855
a61af66fc99e Initial load
duke
parents:
diff changeset
1856 Interval* spilled_part = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1857 if (interval->to() != to_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1858 // the part after to_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1859 spilled_part = interval->split_from_start(to_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1860 append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1861 move_resolver.add_mapping(spilled_part, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1862 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1863 assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1864
a61af66fc99e Initial load
duke
parents:
diff changeset
1865 assert(spilled_part->from() == from_op_id && spilled_part->to() == to_op_id, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1866 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1868
a61af66fc99e Initial load
duke
parents:
diff changeset
1869 void LinearScan::resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1870 assert(block->is_set(BlockBegin::exception_entry_flag), "should not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1871 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1872
a61af66fc99e Initial load
duke
parents:
diff changeset
1873 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1874 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1875 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
1876 resolve_exception_entry(block, r, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1877 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1878
a61af66fc99e Initial load
duke
parents:
diff changeset
1879 // 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
1880 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1881 resolve_exception_entry(block, phi->operand()->vreg_number(), move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1882 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1883
a61af66fc99e Initial load
duke
parents:
diff changeset
1884 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1885 // insert moves after first instruction
5906
b279f99d7143 6910461: Register allocator may insert spill code at wrong insertion index
roland
parents: 4948
diff changeset
1886 move_resolver.set_insert_position(block->lir(), 0);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1887 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1888 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1890
a61af66fc99e Initial load
duke
parents:
diff changeset
1891
a61af66fc99e Initial load
duke
parents:
diff changeset
1892 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
1893 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1894 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1895 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1897
a61af66fc99e Initial load
duke
parents:
diff changeset
1898 // the computation of to_interval is equal to resolve_collect_mappings,
a61af66fc99e Initial load
duke
parents:
diff changeset
1899 // but from_interval is more complicated because of phi functions
a61af66fc99e Initial load
duke
parents:
diff changeset
1900 BlockBegin* to_block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1901 Interval* to_interval = interval_at_block_begin(to_block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1902
a61af66fc99e Initial load
duke
parents:
diff changeset
1903 if (phi != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1904 // phi function of the exception entry block
a61af66fc99e Initial load
duke
parents:
diff changeset
1905 // no moves are created for this phi function in the LIR_Generator, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
1906 // interval at the throwing instruction must be searched using the operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1907 // of the phi function
a61af66fc99e Initial load
duke
parents:
diff changeset
1908 Value from_value = phi->operand_at(handler->phi_operand());
a61af66fc99e Initial load
duke
parents:
diff changeset
1909
a61af66fc99e Initial load
duke
parents:
diff changeset
1910 // with phi functions it can happen that the same from_value is used in
a61af66fc99e Initial load
duke
parents:
diff changeset
1911 // multiple mappings, so notify move-resolver that this is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
1912 move_resolver.set_multiple_reads_allowed();
a61af66fc99e Initial load
duke
parents:
diff changeset
1913
a61af66fc99e Initial load
duke
parents:
diff changeset
1914 Constant* con = from_value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
1915 if (con != NULL && !con->is_pinned()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1916 // unpinned constants may have no register, so add mapping from constant to interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1917 move_resolver.add_mapping(LIR_OprFact::value_type(con->type()), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1918 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1919 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1920 Interval* from_interval = interval_at_op_id(from_value->operand()->vreg_number(), throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1921 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1922 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1923
a61af66fc99e Initial load
duke
parents:
diff changeset
1924 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1925 // no phi function, so use reg_num also for from_interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1926 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1927 Interval* from_interval = interval_at_op_id(reg_num, throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1928 if (from_interval != to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1929 // optimization to reduce number of moves: when to_interval is on stack and
a61af66fc99e Initial load
duke
parents:
diff changeset
1930 // the stack slot is known to be always correct, then no move is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
1931 if (!from_interval->always_in_memory() || from_interval->canonical_spill_slot() != to_interval->assigned_reg()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1932 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1935 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1937
a61af66fc99e Initial load
duke
parents:
diff changeset
1938 void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1939 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
1940
a61af66fc99e Initial load
duke
parents:
diff changeset
1941 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1942 assert(handler->lir_op_id() == -1, "already processed this xhandler");
a61af66fc99e Initial load
duke
parents:
diff changeset
1943 DEBUG_ONLY(handler->set_lir_op_id(throwing_op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
1944 assert(handler->entry_code() == NULL, "code already present");
a61af66fc99e Initial load
duke
parents:
diff changeset
1945
a61af66fc99e Initial load
duke
parents:
diff changeset
1946 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 BlockBegin* block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1948 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1949 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
1950 resolve_exception_edge(handler, throwing_op_id, r, NULL, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1951 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1952
a61af66fc99e Initial load
duke
parents:
diff changeset
1953 // 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
1954 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1955 resolve_exception_edge(handler, throwing_op_id, phi->operand()->vreg_number(), phi, move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1956 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1957
a61af66fc99e Initial load
duke
parents:
diff changeset
1958 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1959 LIR_List* entry_code = new LIR_List(compilation());
a61af66fc99e Initial load
duke
parents:
diff changeset
1960 move_resolver.set_insert_position(entry_code, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1961 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1962
a61af66fc99e Initial load
duke
parents:
diff changeset
1963 entry_code->jump(handler->entry_block());
a61af66fc99e Initial load
duke
parents:
diff changeset
1964 handler->set_entry_code(entry_code);
a61af66fc99e Initial load
duke
parents:
diff changeset
1965 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1966 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1967
a61af66fc99e Initial load
duke
parents:
diff changeset
1968
a61af66fc99e Initial load
duke
parents:
diff changeset
1969 void LinearScan::resolve_exception_handlers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1970 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1971 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1972 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1973
a61af66fc99e Initial load
duke
parents:
diff changeset
1974 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1975 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1976 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1977 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1978 resolve_exception_entry(block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1981
a61af66fc99e Initial load
duke
parents:
diff changeset
1982 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1984 LIR_List* ops = block->lir();
a61af66fc99e Initial load
duke
parents:
diff changeset
1985 int num_ops = ops->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1986
a61af66fc99e Initial load
duke
parents:
diff changeset
1987 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1988 assert(visitor.no_operands(ops->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1989 for (int j = 1; j < num_ops; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1990 LIR_Op* op = ops->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1991 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1992
a61af66fc99e Initial load
duke
parents:
diff changeset
1993 if (op_id != -1 && has_info(op_id)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1995 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 assert(visitor.info_count() > 0, "should not visit otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1997
a61af66fc99e Initial load
duke
parents:
diff changeset
1998 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2000 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 resolve_exception_edge(xhandlers->handler_at(k), op_id, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
2002 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2003
a61af66fc99e Initial load
duke
parents:
diff changeset
2004 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2006 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2007 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2008 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2009 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2010 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2011 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2013
a61af66fc99e Initial load
duke
parents:
diff changeset
2014
a61af66fc99e Initial load
duke
parents:
diff changeset
2015 // ********** Phase 7: assign register numbers back to LIR
a61af66fc99e Initial load
duke
parents:
diff changeset
2016 // (includes computation of debug information and oop maps)
a61af66fc99e Initial load
duke
parents:
diff changeset
2017
a61af66fc99e Initial load
duke
parents:
diff changeset
2018 VMReg LinearScan::vm_reg_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2019 VMReg reg = interval->cached_vm_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2020 if (!reg->is_valid() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2021 reg = vm_reg_for_operand(operand_for_interval(interval));
a61af66fc99e Initial load
duke
parents:
diff changeset
2022 interval->set_cached_vm_reg(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2023 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2024 assert(reg == vm_reg_for_operand(operand_for_interval(interval)), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 return reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2027
a61af66fc99e Initial load
duke
parents:
diff changeset
2028 VMReg LinearScan::vm_reg_for_operand(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2029 assert(opr->is_oop(), "currently only implemented for oop operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2030 return frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2031 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2032
a61af66fc99e Initial load
duke
parents:
diff changeset
2033
a61af66fc99e Initial load
duke
parents:
diff changeset
2034 LIR_Opr LinearScan::operand_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2035 LIR_Opr opr = interval->cached_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2036 if (opr->is_illegal()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2037 opr = calc_operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2038 interval->set_cached_opr(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2040
a61af66fc99e Initial load
duke
parents:
diff changeset
2041 assert(opr == calc_operand_for_interval(interval), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2042 return opr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2043 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2044
a61af66fc99e Initial load
duke
parents:
diff changeset
2045 LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2046 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2047 BasicType type = interval->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2048
a61af66fc99e Initial load
duke
parents:
diff changeset
2049 if (assigned_reg >= nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2050 // stack slot
a61af66fc99e Initial load
duke
parents:
diff changeset
2051 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2052 return LIR_OprFact::stack(assigned_reg - nof_regs, type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2053
a61af66fc99e Initial load
duke
parents:
diff changeset
2054 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2055 // register
a61af66fc99e Initial load
duke
parents:
diff changeset
2056 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2057 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2058 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2059 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2060 return LIR_OprFact::single_cpu_oop(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2061 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2062
1816
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2063 case T_ADDRESS: {
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2064 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
2065 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
2066 return LIR_OprFact::single_cpu_address(assigned_reg);
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2067 }
87b64980e2f1 6972540: sun/nio/ch/SocketChannelImpl compilation crashed when executing CompileTheWorld
never
parents: 1681
diff changeset
2068
6739
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2069 case T_METADATA: {
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2070 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
2071 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2072 return LIR_OprFact::single_cpu_metadata(assigned_reg);
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2073 }
8a02ca5e5576 7195816: NPG: Crash in c1_ValueType - ShouldNotReachHere
roland
parents: 6197
diff changeset
2074
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2075 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2076 case T_FLOAT: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2077 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2078 case T_INT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2079 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2080 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2081 return LIR_OprFact::single_cpu(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2082 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2083
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2084 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2085 case T_DOUBLE: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2086 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2087 case T_LONG: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2088 int assigned_regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
2089 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2090 assert(num_physical_regs(T_LONG) == 1 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2091 (assigned_regHi >= pd_first_cpu_reg && assigned_regHi <= pd_last_cpu_reg), "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2092
a61af66fc99e Initial load
duke
parents:
diff changeset
2093 assert(assigned_reg != assigned_regHi, "invalid allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 assert(num_physical_regs(T_LONG) == 1 || assigned_reg < assigned_regHi,
a61af66fc99e Initial load
duke
parents:
diff changeset
2095 "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
2096 assert((assigned_regHi != any_reg) ^ (num_physical_regs(T_LONG) == 1), "must be match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2097 if (requires_adjacent_regs(T_LONG)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == assigned_regHi, "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2099 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2100
a61af66fc99e Initial load
duke
parents:
diff changeset
2101 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2102 return LIR_OprFact::double_cpu(assigned_reg, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2103 #else
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2104 #if defined(SPARC) || defined(PPC)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2105 return LIR_OprFact::double_cpu(assigned_regHi, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2106 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2107 return LIR_OprFact::double_cpu(assigned_reg, assigned_regHi);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2108 #endif // SPARC
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2109 #endif // LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2110 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2111
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2112 #ifndef __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2113 case T_FLOAT: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2114 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2115 if (UseSSE >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2116 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2117 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 return LIR_OprFact::single_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2121
a61af66fc99e Initial load
duke
parents:
diff changeset
2122 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2123 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2124 return LIR_OprFact::single_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2126
a61af66fc99e Initial load
duke
parents:
diff changeset
2127 case T_DOUBLE: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2128 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2129 if (UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2131 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
2132 return LIR_OprFact::double_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2135
a61af66fc99e Initial load
duke
parents:
diff changeset
2136 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2138 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
2139 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2140 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
2141 #elif defined(ARM)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2142 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
2143 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
2144 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
2145 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
2146 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2147 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2148 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
2149 LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
2152 }
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2153 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2154
a61af66fc99e Initial load
duke
parents:
diff changeset
2155 default: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2156 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2157 return LIR_OprFact::illegalOpr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2160 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2162
a61af66fc99e Initial load
duke
parents:
diff changeset
2163 LIR_Opr LinearScan::canonical_spill_opr(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2164 assert(interval->canonical_spill_slot() >= nof_regs, "canonical spill slot not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2165 return LIR_OprFact::stack(interval->canonical_spill_slot() - nof_regs, interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2167
a61af66fc99e Initial load
duke
parents:
diff changeset
2168 LIR_Opr LinearScan::color_lir_opr(LIR_Opr opr, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2169 assert(opr->is_virtual(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2170
a61af66fc99e Initial load
duke
parents:
diff changeset
2171 Interval* interval = interval_at(opr->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
2172 assert(interval != NULL, "interval must exist");
a61af66fc99e Initial load
duke
parents:
diff changeset
2173
a61af66fc99e Initial load
duke
parents:
diff changeset
2174 if (op_id != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2175 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2176 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2177 if (block->number_of_sux() <= 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2178 // check if spill moves could have been appended at the end of this block, but
a61af66fc99e Initial load
duke
parents:
diff changeset
2179 // before the branch instruction. So the split child information for this branch would
a61af66fc99e Initial load
duke
parents:
diff changeset
2180 // be incorrect.
a61af66fc99e Initial load
duke
parents:
diff changeset
2181 LIR_OpBranch* branch = block->lir()->instructions_list()->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
2182 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2183 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2184 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
2185 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
2186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2189 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2190
a61af66fc99e Initial load
duke
parents:
diff changeset
2191 // operands are not changed when an interval is split during allocation,
a61af66fc99e Initial load
duke
parents:
diff changeset
2192 // so search the right interval here
a61af66fc99e Initial load
duke
parents:
diff changeset
2193 interval = split_child_at_op_id(interval, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2195
a61af66fc99e Initial load
duke
parents:
diff changeset
2196 LIR_Opr res = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2197
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2198 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2199 // new semantic for is_last_use: not only set on definite end of interval,
a61af66fc99e Initial load
duke
parents:
diff changeset
2200 // but also before hole
a61af66fc99e Initial load
duke
parents:
diff changeset
2201 // 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
2202 // last use information is completely correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2203 // information is only needed for fpu stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
2204 if (res->is_fpu_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2205 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
2206 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
2207 res = res->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
2208 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2210 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2211
a61af66fc99e Initial load
duke
parents:
diff changeset
2212 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
2213
a61af66fc99e Initial load
duke
parents:
diff changeset
2214 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2216
a61af66fc99e Initial load
duke
parents:
diff changeset
2217
a61af66fc99e Initial load
duke
parents:
diff changeset
2218 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2219 // some methods used to check correctness of debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2220
a61af66fc99e Initial load
duke
parents:
diff changeset
2221 void assert_no_register_values(GrowableArray<ScopeValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2222 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2223 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2224 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2225
a61af66fc99e Initial load
duke
parents:
diff changeset
2226 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2227 ScopeValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2228
a61af66fc99e Initial load
duke
parents:
diff changeset
2229 if (value->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 Location location = ((LocationValue*)value)->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2231 assert(location.where() == Location::on_stack, "value is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2232 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2235
a61af66fc99e Initial load
duke
parents:
diff changeset
2236 void assert_no_register_values(GrowableArray<MonitorValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2238 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2239 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2240
a61af66fc99e Initial load
duke
parents:
diff changeset
2241 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 MonitorValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2243
a61af66fc99e Initial load
duke
parents:
diff changeset
2244 if (value->owner()->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2245 Location location = ((LocationValue*)value->owner())->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2246 assert(location.where() == Location::on_stack, "owner is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2248 assert(value->basic_lock().where() == Location::on_stack, "basic_lock is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2251
a61af66fc99e Initial load
duke
parents:
diff changeset
2252 void assert_equal(Location l1, Location l2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2255
a61af66fc99e Initial load
duke
parents:
diff changeset
2256 void assert_equal(ScopeValue* v1, ScopeValue* v2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 if (v1->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2258 assert(v2->is_location(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2259 assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location());
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 } else if (v1->is_constant_int()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2261 assert(v2->is_constant_int(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 assert(((ConstantIntValue*)v1)->value() == ((ConstantIntValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 } else if (v1->is_constant_double()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2264 assert(v2->is_constant_double(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 assert(((ConstantDoubleValue*)v1)->value() == ((ConstantDoubleValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 } else if (v1->is_constant_long()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 assert(v2->is_constant_long(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 assert(((ConstantLongValue*)v1)->value() == ((ConstantLongValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2269 } else if (v1->is_constant_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2270 assert(v2->is_constant_oop(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2271 assert(((ConstantOopWriteValue*)v1)->value() == ((ConstantOopWriteValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2276
a61af66fc99e Initial load
duke
parents:
diff changeset
2277 void assert_equal(MonitorValue* m1, MonitorValue* m2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 assert_equal(m1->owner(), m2->owner());
a61af66fc99e Initial load
duke
parents:
diff changeset
2279 assert_equal(m1->basic_lock(), m2->basic_lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2281
a61af66fc99e Initial load
duke
parents:
diff changeset
2282 void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2283 assert(d1->scope() == d2->scope(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2284 assert(d1->bci() == d2->bci(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2285
a61af66fc99e Initial load
duke
parents:
diff changeset
2286 if (d1->locals() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2287 assert(d1->locals() != NULL && d2->locals() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2288 assert(d1->locals()->length() == d2->locals()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2289 for (int i = 0; i < d1->locals()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2290 assert_equal(d1->locals()->at(i), d2->locals()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2291 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2292 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2293 assert(d1->locals() == NULL && d2->locals() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2295
a61af66fc99e Initial load
duke
parents:
diff changeset
2296 if (d1->expressions() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2297 assert(d1->expressions() != NULL && d2->expressions() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2298 assert(d1->expressions()->length() == d2->expressions()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2299 for (int i = 0; i < d1->expressions()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2300 assert_equal(d1->expressions()->at(i), d2->expressions()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2301 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2302 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2303 assert(d1->expressions() == NULL && d2->expressions() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2305
a61af66fc99e Initial load
duke
parents:
diff changeset
2306 if (d1->monitors() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2307 assert(d1->monitors() != NULL && d2->monitors() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2308 assert(d1->monitors()->length() == d2->monitors()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2309 for (int i = 0; i < d1->monitors()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2310 assert_equal(d1->monitors()->at(i), d2->monitors()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2312 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2313 assert(d1->monitors() == NULL && d2->monitors() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2315
a61af66fc99e Initial load
duke
parents:
diff changeset
2316 if (d1->caller() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2317 assert(d1->caller() != NULL && d2->caller() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2318 assert_equal(d1->caller(), d2->caller());
a61af66fc99e Initial load
duke
parents:
diff changeset
2319 } else {
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 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2323
a61af66fc99e Initial load
duke
parents:
diff changeset
2324 void check_stack_depth(CodeEmitInfo* info, int stack_end) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2325 if (info->stack()->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2326 Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->stack()->bci());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2327 switch (code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2328 case Bytecodes::_ifnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2329 case Bytecodes::_ifnonnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2330 case Bytecodes::_ifeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2331 case Bytecodes::_ifne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2332 case Bytecodes::_iflt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2333 case Bytecodes::_ifge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2334 case Bytecodes::_ifgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2335 case Bytecodes::_ifle : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2336 case Bytecodes::_if_icmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2337 case Bytecodes::_if_icmpne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2338 case Bytecodes::_if_icmplt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2339 case Bytecodes::_if_icmpge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2340 case Bytecodes::_if_icmpgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2341 case Bytecodes::_if_icmple : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2342 case Bytecodes::_if_acmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2343 case Bytecodes::_if_acmpne :
a61af66fc99e Initial load
duke
parents:
diff changeset
2344 assert(stack_end >= -Bytecodes::depth(code), "must have non-empty expression stack at if bytecode");
a61af66fc99e Initial load
duke
parents:
diff changeset
2345 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2346 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2347 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2349
a61af66fc99e Initial load
duke
parents:
diff changeset
2350 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2351
a61af66fc99e Initial load
duke
parents:
diff changeset
2352
a61af66fc99e Initial load
duke
parents:
diff changeset
2353 IntervalWalker* LinearScan::init_compute_oop_maps() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2354 // setup lists of potential oops for walking
a61af66fc99e Initial load
duke
parents:
diff changeset
2355 Interval* oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2356 Interval* non_oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2357
a61af66fc99e Initial load
duke
parents:
diff changeset
2358 create_unhandled_lists(&oop_intervals, &non_oop_intervals, is_oop_interval, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2359
a61af66fc99e Initial load
duke
parents:
diff changeset
2360 // intervals that have no oops inside need not to be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
2361 // to ensure a walking until the last instruction id, add a dummy interval
a61af66fc99e Initial load
duke
parents:
diff changeset
2362 // with a high operation id
a61af66fc99e Initial load
duke
parents:
diff changeset
2363 non_oop_intervals = new Interval(any_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2364 non_oop_intervals->add_range(max_jint - 2, max_jint - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2365
a61af66fc99e Initial load
duke
parents:
diff changeset
2366 return new IntervalWalker(this, oop_intervals, non_oop_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2367 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2368
a61af66fc99e Initial load
duke
parents:
diff changeset
2369
a61af66fc99e Initial load
duke
parents:
diff changeset
2370 OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2371 TRACE_LINEAR_SCAN(3, tty->print_cr("creating oop map at op_id %d", op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2372
a61af66fc99e Initial load
duke
parents:
diff changeset
2373 // walk before the current operation -> intervals that start at
a61af66fc99e Initial load
duke
parents:
diff changeset
2374 // the operation (= output operands of the operation) are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2375 // included in the oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2376 iw->walk_before(op->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
2377
a61af66fc99e Initial load
duke
parents:
diff changeset
2378 int frame_size = frame_map()->framesize();
a61af66fc99e Initial load
duke
parents:
diff changeset
2379 int arg_count = frame_map()->oop_map_arg_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2380 OopMap* map = new OopMap(frame_size, arg_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2381
a61af66fc99e Initial load
duke
parents:
diff changeset
2382 // Iterate through active intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2383 for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2384 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2385
a61af66fc99e Initial load
duke
parents:
diff changeset
2386 assert(interval->current_from() <= op->id() && op->id() <= interval->current_to(), "interval should not be active otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2387 assert(interval->assigned_regHi() == any_reg, "oop must be single word");
a61af66fc99e Initial load
duke
parents:
diff changeset
2388 assert(interval->reg_num() >= LIR_OprDesc::vreg_base, "fixed interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
2389
a61af66fc99e Initial load
duke
parents:
diff changeset
2390 // Check if this range covers the instruction. Intervals that
a61af66fc99e Initial load
duke
parents:
diff changeset
2391 // start or end at the current operation are not included in the
a61af66fc99e Initial load
duke
parents:
diff changeset
2392 // oop map, except in the case of patching moves. For patching
a61af66fc99e Initial load
duke
parents:
diff changeset
2393 // moves, any intervals which end at this instruction are included
a61af66fc99e Initial load
duke
parents:
diff changeset
2394 // in the oop map since we may safepoint while doing the patch
a61af66fc99e Initial load
duke
parents:
diff changeset
2395 // before we've consumed the inputs.
17945
15766b73dc1d 8031475: Missing oopmap in patching stubs
neliasso
parents: 17467
diff changeset
2396 if (op->is_patching() || op->id() < interval->current_to()) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2397
a61af66fc99e Initial load
duke
parents:
diff changeset
2398 // caller-save registers must not be included into oop-maps at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
2399 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
2400
a61af66fc99e Initial load
duke
parents:
diff changeset
2401 VMReg name = vm_reg_for_interval(interval);
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2402 set_oop(map, name);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2403
a61af66fc99e Initial load
duke
parents:
diff changeset
2404 // Spill optimization: when the stack value is guaranteed to be always correct,
a61af66fc99e Initial load
duke
parents:
diff changeset
2405 // 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
2406 if (interval->always_in_memory() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2407 op->id() > interval->spill_definition_pos() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2408 interval->assigned_reg() != interval->canonical_spill_slot()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2409 assert(interval->spill_definition_pos() > 0, "position not set correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
2410 assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
2411 assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
2412
3908
7588156f5cf9 7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents: 2426
diff changeset
2413 set_oop(map, frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2415 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2416 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2417
a61af66fc99e Initial load
duke
parents:
diff changeset
2418 // add oops from lock stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2419 assert(info->stack() != NULL, "CodeEmitInfo must always have a stack");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2420 int locks_count = info->stack()->total_locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2421 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
2422 set_oop(map, frame_map()->monitor_object_regname(i));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2424
a61af66fc99e Initial load
duke
parents:
diff changeset
2425 return map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2426 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2427
a61af66fc99e Initial load
duke
parents:
diff changeset
2428
a61af66fc99e Initial load
duke
parents:
diff changeset
2429 void LinearScan::compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2430 assert(visitor.info_count() > 0, "no oop map needed");
a61af66fc99e Initial load
duke
parents:
diff changeset
2431
a61af66fc99e Initial load
duke
parents:
diff changeset
2432 // compute oop_map only for first CodeEmitInfo
a61af66fc99e Initial load
duke
parents:
diff changeset
2433 // because it is (in most cases) equal for all other infos of the same operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2434 CodeEmitInfo* first_info = visitor.info_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2435 OopMap* first_oop_map = compute_oop_map(iw, op, first_info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2436
a61af66fc99e Initial load
duke
parents:
diff changeset
2437 for (int i = 0; i < visitor.info_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2438 CodeEmitInfo* info = visitor.info_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2439 OopMap* oop_map = first_oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2440
17980
0bf37f737702 8032410: compiler/uncommontrap/TestStackBangRbp.java times out on Solaris-Sparc V9
roland
parents: 17945
diff changeset
2441 // compute worst case interpreter size in case of a deoptimization
0bf37f737702 8032410: compiler/uncommontrap/TestStackBangRbp.java times out on Solaris-Sparc V9
roland
parents: 17945
diff changeset
2442 _compilation->update_interpreter_frame_size(info->interpreter_frame_size());
0bf37f737702 8032410: compiler/uncommontrap/TestStackBangRbp.java times out on Solaris-Sparc V9
roland
parents: 17945
diff changeset
2443
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2444 if (info->stack()->locks_size() != first_info->stack()->locks_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2445 // this info has a different number of locks then the precomputed oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2446 // (possible for lock and unlock instructions) -> compute oop map with
a61af66fc99e Initial load
duke
parents:
diff changeset
2447 // correct lock information
a61af66fc99e Initial load
duke
parents:
diff changeset
2448 oop_map = compute_oop_map(iw, op, info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2450
a61af66fc99e Initial load
duke
parents:
diff changeset
2451 if (info->_oop_map == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2452 info->_oop_map = oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2453 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2454 // a CodeEmitInfo can not be shared between different LIR-instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2455 // because interval splitting can occur anywhere between two instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2456 // and so the oop maps must be different
a61af66fc99e Initial load
duke
parents:
diff changeset
2457 // -> check if the already set oop_map is exactly the one calculated for this operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2458 assert(info->_oop_map == oop_map, "same CodeEmitInfo used for multiple LIR instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
2459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2461 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2462
a61af66fc99e Initial load
duke
parents:
diff changeset
2463
a61af66fc99e Initial load
duke
parents:
diff changeset
2464 // frequently used constants
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2465 // 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
2466 // 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
2467 // use).
6197
d2a62e0f25eb 6995781: Native Memory Tracking (Phase 1)
zgu
parents: 6084
diff changeset
2468 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
2469 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
2470 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
2471 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
2472 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
2473 LocationValue* _illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2474
a61af66fc99e Initial load
duke
parents:
diff changeset
2475 void LinearScan::init_compute_debug_info() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2476 // cache for frequently used scope values
a61af66fc99e Initial load
duke
parents:
diff changeset
2477 // (cpu registers and stack slots)
a61af66fc99e Initial load
duke
parents:
diff changeset
2478 _scope_value_cache = ScopeValueArray((LinearScan::nof_cpu_regs + frame_map()->argcount() + max_spills()) * 2, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2480
a61af66fc99e Initial load
duke
parents:
diff changeset
2481 MonitorValue* LinearScan::location_for_monitor_index(int monitor_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2482 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2483 if (!frame_map()->location_for_monitor_object(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2484 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2485 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2486 ScopeValue* object_scope_value = new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2487
a61af66fc99e Initial load
duke
parents:
diff changeset
2488 if (!frame_map()->location_for_monitor_lock(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2489 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2491 return new MonitorValue(object_scope_value, loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2493
a61af66fc99e Initial load
duke
parents:
diff changeset
2494 LocationValue* LinearScan::location_for_name(int name, Location::Type loc_type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2495 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2496 if (!frame_map()->locations_for_slot(name, loc_type, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2497 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2499 return new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2501
a61af66fc99e Initial load
duke
parents:
diff changeset
2502
a61af66fc99e Initial load
duke
parents:
diff changeset
2503 int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2504 assert(opr->is_constant(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2505
a61af66fc99e Initial load
duke
parents:
diff changeset
2506 LIR_Const* c = opr->as_constant_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2507 BasicType t = c->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2508 switch (t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2509 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2510 jobject value = c->as_jobject();
a61af66fc99e Initial load
duke
parents:
diff changeset
2511 if (value == NULL) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2512 scope_values->append(_oop_null_scope_value);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2513 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2514 scope_values->append(new ConstantOopWriteValue(c->as_jobject()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2515 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2516 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2517 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2518
a61af66fc99e Initial load
duke
parents:
diff changeset
2519 case T_INT: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2520 case T_FLOAT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2521 int value = c->as_jint_bits();
a61af66fc99e Initial load
duke
parents:
diff changeset
2522 switch (value) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2523 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
2524 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
2525 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
2526 case 2: scope_values->append(_int_2_scope_value); break;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2527 default: scope_values->append(new ConstantIntValue(c->as_jint_bits())); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2528 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2529 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2530 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2531
a61af66fc99e Initial load
duke
parents:
diff changeset
2532 case T_LONG: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2533 case T_DOUBLE: {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2534 #ifdef _LP64
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2535 scope_values->append(_int_0_scope_value);
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2536 scope_values->append(new ConstantLongValue(c->as_jlong_bits()));
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2537 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2538 if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2539 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2540 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2541 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2542 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2543 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2544 }
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2545 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2546 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2547 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2548
1297
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2549 case T_ADDRESS: {
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2550 #ifdef _LP64
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2551 scope_values->append(new ConstantLongValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2552 #else
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2553 scope_values->append(new ConstantIntValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2554 #endif
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2555 return 1;
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2556 }
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2557
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2558 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
2559 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2560 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2561 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2563
a61af66fc99e Initial load
duke
parents:
diff changeset
2564 int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2565 if (opr->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2566 int stack_idx = opr->single_stack_ix();
a61af66fc99e Initial load
duke
parents:
diff changeset
2567 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2568 int cache_idx = (stack_idx + LinearScan::nof_cpu_regs) * 2 + (is_oop ? 1 : 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2569
a61af66fc99e Initial load
duke
parents:
diff changeset
2570 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2571 if (sv == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2572 Location::Type loc_type = is_oop ? Location::oop : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2573 sv = location_for_name(stack_idx, loc_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2574 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2576
a61af66fc99e Initial load
duke
parents:
diff changeset
2577 // check if cached value is correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2578 DEBUG_ONLY(assert_equal(sv, location_for_name(stack_idx, is_oop ? Location::oop : Location::normal)));
a61af66fc99e Initial load
duke
parents:
diff changeset
2579
a61af66fc99e Initial load
duke
parents:
diff changeset
2580 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2581 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2582
a61af66fc99e Initial load
duke
parents:
diff changeset
2583 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2584 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2585 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
2586 Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2587
a61af66fc99e Initial load
duke
parents:
diff changeset
2588 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2589 if (sv == NULL) {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2590 Location::Type loc_type = is_oop ? Location::oop : int_loc_type;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2591 VMReg rname = frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2592 sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2593 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2595
a61af66fc99e Initial load
duke
parents:
diff changeset
2596 // check if cached value is correct
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2597 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
2598
a61af66fc99e Initial load
duke
parents:
diff changeset
2599 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2600 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2601
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2602 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2603 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2604 VMReg rname = opr->as_xmm_float_reg()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2605 LocationValue* sv = new LocationValue(Location::new_reg_loc(Location::normal, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2606
a61af66fc99e Initial load
duke
parents:
diff changeset
2607 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2608 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2609 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2610
a61af66fc99e Initial load
duke
parents:
diff changeset
2611 } else if (opr->is_single_fpu()) {
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 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2614 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2615 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2616 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
2617 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2618 opr = _fpu_stack_allocator->to_fpu_stack(opr);
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 Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2622 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
2623 #ifndef __SOFTFP__
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2624 #ifndef VM_LITTLE_ENDIAN
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2625 if (! float_saved_as_double) {
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2626 // 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
2627 // the low half of the (same) double registers.
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2628 // 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
2629 // to two different addresses once saved.
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2630
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2631 // get next safely (no assertion checks)
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2632 VMReg next = VMRegImpl::as_VMReg(1+rname->value());
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2633 if (next->is_reg() &&
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2634 (next->as_FloatRegister() == rname->as_FloatRegister())) {
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2635 // 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
2636 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
2637 }
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2638 }
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2639 #endif
eba73e0c7780 7096366: PPC: corruption of floating-point values with DeoptimizeALot
bdelsart
parents: 3908
diff changeset
2640 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2641 LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2642
a61af66fc99e Initial load
duke
parents:
diff changeset
2643 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2644 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2645
a61af66fc99e Initial load
duke
parents:
diff changeset
2646 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2647 // double-size operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2648
a61af66fc99e Initial load
duke
parents:
diff changeset
2649 ScopeValue* first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2650 ScopeValue* second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2651
a61af66fc99e Initial load
duke
parents:
diff changeset
2652 if (opr->is_double_stack()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2653 #ifdef _LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2654 Location loc1;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2655 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
2656 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
2657 bailout("too large frame");
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2658 }
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2659 // Does this reverse on x86 vs. sparc?
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2660 first = new LocationValue(loc1);
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2661 second = _int_0_scope_value;
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2662 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2663 Location loc1, loc2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2664 if (!frame_map()->locations_for_slot(opr->double_stack_ix(), Location::normal, &loc1, &loc2)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2665 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2666 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2667 first = new LocationValue(loc1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2668 second = new LocationValue(loc2);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2669 #endif // _LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2670
a61af66fc99e Initial load
duke
parents:
diff changeset
2671 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2672 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2673 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2674 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
2675 second = _int_0_scope_value;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2676 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2677 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2678 VMReg rname_second = opr->as_register_hi()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2679
a61af66fc99e Initial load
duke
parents:
diff changeset
2680 if (hi_word_offset_in_bytes < lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2681 // lo/hi and swapped relative to first and second, so swap them
a61af66fc99e Initial load
duke
parents:
diff changeset
2682 VMReg tmp = rname_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2683 rname_first = rname_second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2684 rname_second = tmp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2685 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2686
a61af66fc99e Initial load
duke
parents:
diff changeset
2687 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2688 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
2689 #endif //_LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2690
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2691
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2692 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2693 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2694 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2695 VMReg rname_first = opr->as_xmm_double_reg()->as_VMReg();
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2696 # ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2697 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
2698 second = _int_0_scope_value;
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2699 # else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2700 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2701 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2702 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2703 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2704 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2705 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2706 # endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2707 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2708
a61af66fc99e Initial load
duke
parents:
diff changeset
2709 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2710 // 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
2711 // the double as float registers in the native ordering. On X86,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2712 // fpu_regnrLo is a FPU stack slot whose VMReg represents
a61af66fc99e Initial load
duke
parents:
diff changeset
2713 // the low-order word of the double and fpu_regnrLo + 1 is the
a61af66fc99e Initial load
duke
parents:
diff changeset
2714 // name for the other half. *first and *second must represent the
a61af66fc99e Initial load
duke
parents:
diff changeset
2715 // least and most significant words, respectively.
a61af66fc99e Initial load
duke
parents:
diff changeset
2716
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2717 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2718 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2719 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2720 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2721 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
2722 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2723 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2724
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2725 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrLo is used)");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2726 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2727 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2728 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2729 #endif
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2730 #ifdef ARM
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2731 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
2732 #endif
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2733 #ifdef PPC
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2734 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
2735 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2736
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2737 #ifdef VM_LITTLE_ENDIAN
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2738 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrLo());
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2739 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2740 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi());
2345
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2741 #endif
b9684d5ccb52 7011490: Wrong computation results in Test6880034
vladidan
parents: 2192
diff changeset
2742
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2743 #ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2744 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
2745 second = _int_0_scope_value;
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2746 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2747 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2748 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2749 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2750 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2751 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2752 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2753 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2754
a61af66fc99e Initial load
duke
parents:
diff changeset
2755 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2756 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2757 first = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2758 second = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2759 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2760
a61af66fc99e Initial load
duke
parents:
diff changeset
2761 assert(first != NULL && second != NULL, "must be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2762 // The convention the interpreter uses is that the second local
a61af66fc99e Initial load
duke
parents:
diff changeset
2763 // holds the first raw word of the native double representation.
a61af66fc99e Initial load
duke
parents:
diff changeset
2764 // This is actually reasonable, since locals and stack arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2765 // grow downwards in all implementations.
a61af66fc99e Initial load
duke
parents:
diff changeset
2766 // (If, on some machine, the interpreter's Java locals or stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2767 // were to grow upwards, the embedded doubles would be word-swapped.)
a61af66fc99e Initial load
duke
parents:
diff changeset
2768 scope_values->append(second);
a61af66fc99e Initial load
duke
parents:
diff changeset
2769 scope_values->append(first);
a61af66fc99e Initial load
duke
parents:
diff changeset
2770 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2771 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2772 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2773
a61af66fc99e Initial load
duke
parents:
diff changeset
2774
a61af66fc99e Initial load
duke
parents:
diff changeset
2775 int LinearScan::append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2776 if (value != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2777 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
2778 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
2779
a61af66fc99e Initial load
duke
parents:
diff changeset
2780 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
2781 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2782
a61af66fc99e Initial load
duke
parents:
diff changeset
2783 if (con != NULL && !con->is_pinned() && !opr->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2784 // Unpinned constants may have a virtual operand for a part of the lifetime
a61af66fc99e Initial load
duke
parents:
diff changeset
2785 // or may be illegal when it was optimized away,
a61af66fc99e Initial load
duke
parents:
diff changeset
2786 // so always use a constant operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2787 opr = LIR_OprFact::value_type(con->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2788 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2789 assert(opr->is_virtual() || opr->is_constant(), "other cases not allowed here");
a61af66fc99e Initial load
duke
parents:
diff changeset
2790
a61af66fc99e Initial load
duke
parents:
diff changeset
2791 if (opr->is_virtual()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2792 LIR_OpVisitState::OprMode mode = LIR_OpVisitState::inputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2793
a61af66fc99e Initial load
duke
parents:
diff changeset
2794 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2795 if (block->number_of_sux() == 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2796 // generating debug information for the last instruction of a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
2797 // if this instruction is a branch, spill moves are inserted before this branch
a61af66fc99e Initial load
duke
parents:
diff changeset
2798 // and so the wrong operand would be returned (spill moves at block boundaries are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2799 // considered in the live ranges of intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
2800 // Solution: use the first op_id of the branch target block instead.
a61af66fc99e Initial load
duke
parents:
diff changeset
2801 if (block->lir()->instructions_list()->last()->as_OpBranch() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2802 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2803 op_id = block->sux_at(0)->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2804 mode = LIR_OpVisitState::outputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2805 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2806 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2807 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2808
a61af66fc99e Initial load
duke
parents:
diff changeset
2809 // Get current location of operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2810 // The operand must be live because debug information is considered when building the intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2811 // if the interval is not live, color_lir_opr will cause an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
2812 opr = color_lir_opr(opr, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2813 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
2814
a61af66fc99e Initial load
duke
parents:
diff changeset
2815 // Append to ScopeValue array
a61af66fc99e Initial load
duke
parents:
diff changeset
2816 return append_scope_value_for_operand(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2817
a61af66fc99e Initial load
duke
parents:
diff changeset
2818 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2819 assert(value->as_Constant() != NULL, "all other instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2820 assert(opr->is_constant(), "operand must be constant");
a61af66fc99e Initial load
duke
parents:
diff changeset
2821
a61af66fc99e Initial load
duke
parents:
diff changeset
2822 return append_scope_value_for_constant(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2823 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2824 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2825 // 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
2826 scope_values->append(_illegal_value);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2827 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2828 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2829 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2830
a61af66fc99e Initial load
duke
parents:
diff changeset
2831
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2832 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
2833 IRScopeDebugInfo* caller_debug_info = NULL;
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2834
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2835 ValueStack* caller_state = cur_state->caller_state();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2836 if (caller_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2837 // process recursively to compute outermost scope first
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2838 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
2839 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2840
a61af66fc99e Initial load
duke
parents:
diff changeset
2841 // initialize these to null.
a61af66fc99e Initial load
duke
parents:
diff changeset
2842 // If we don't need deopt info or there are no locals, expressions or monitors,
a61af66fc99e Initial load
duke
parents:
diff changeset
2843 // then these get recorded as no information and avoids the allocation of 0 length arrays.
a61af66fc99e Initial load
duke
parents:
diff changeset
2844 GrowableArray<ScopeValue*>* locals = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2845 GrowableArray<ScopeValue*>* expressions = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2846 GrowableArray<MonitorValue*>* monitors = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2847
a61af66fc99e Initial load
duke
parents:
diff changeset
2848 // describe local variable values
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2849 int nof_locals = cur_state->locals_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2850 if (nof_locals > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2851 locals = new GrowableArray<ScopeValue*>(nof_locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2852
a61af66fc99e Initial load
duke
parents:
diff changeset
2853 int pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2854 while (pos < nof_locals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2855 assert(pos < cur_state->locals_size(), "why not?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2856
a61af66fc99e Initial load
duke
parents:
diff changeset
2857 Value local = cur_state->local_at(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2858 pos += append_scope_value(op_id, local, locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2859
a61af66fc99e Initial load
duke
parents:
diff changeset
2860 assert(locals->length() == pos, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2861 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2862 assert(locals->length() == cur_scope->method()->max_locals(), "wrong number of locals");
a61af66fc99e Initial load
duke
parents:
diff changeset
2863 assert(locals->length() == cur_state->locals_size(), "wrong number of locals");
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2864 } else if (cur_scope->method()->max_locals() > 0) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2865 assert(cur_state->kind() == ValueStack::EmptyExceptionState, "should be");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2866 nof_locals = cur_scope->method()->max_locals();
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2867 locals = new GrowableArray<ScopeValue*>(nof_locals);
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2868 for(int i = 0; i < nof_locals; i++) {
4948
c7401dcad8bf 7143038: SIGSEGV in assert_equal / LinearScan::assign_reg_num
roland
parents: 3999
diff changeset
2869 locals->append(_illegal_value);
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2870 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2871 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2872
a61af66fc99e Initial load
duke
parents:
diff changeset
2873 // describe expression stack
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2874 int nof_stack = cur_state->stack_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2875 if (nof_stack > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2876 expressions = new GrowableArray<ScopeValue*>(nof_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
2877
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2878 int pos = 0;
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2879 while (pos < nof_stack) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2880 Value expression = cur_state->stack_at_inc(pos);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2881 append_scope_value(op_id, expression, expressions);
a61af66fc99e Initial load
duke
parents:
diff changeset
2882
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2883 assert(expressions->length() == pos, "must match");
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2884 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2885 assert(expressions->length() == cur_state->stack_size(), "wrong number of stack entries");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2887
a61af66fc99e Initial load
duke
parents:
diff changeset
2888 // describe monitors
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2889 int nof_locks = cur_state->locks_size();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2890 if (nof_locks > 0) {
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2891 int lock_offset = cur_state->caller_state() != NULL ? cur_state->caller_state()->total_locks_size() : 0;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2892 monitors = new GrowableArray<MonitorValue*>(nof_locks);
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2893 for (int i = 0; i < nof_locks; i++) {
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2894 monitors->append(location_for_monitor_index(lock_offset + i));
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2895 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2896 }
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2897
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2898 return new IRScopeDebugInfo(cur_scope, cur_state->bci(), locals, expressions, monitors, caller_debug_info);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2899 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2900
a61af66fc99e Initial load
duke
parents:
diff changeset
2901
a61af66fc99e Initial load
duke
parents:
diff changeset
2902 void LinearScan::compute_debug_info(CodeEmitInfo* info, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2903 TRACE_LINEAR_SCAN(3, tty->print_cr("creating debug information at op_id %d", op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
2904
a61af66fc99e Initial load
duke
parents:
diff changeset
2905 IRScope* innermost_scope = info->scope();
a61af66fc99e Initial load
duke
parents:
diff changeset
2906 ValueStack* innermost_state = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
2907
a61af66fc99e Initial load
duke
parents:
diff changeset
2908 assert(innermost_scope != NULL && innermost_state != NULL, "why is it missing?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2909
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2910 DEBUG_ONLY(check_stack_depth(info, innermost_state->stack_size()));
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2911
a61af66fc99e Initial load
duke
parents:
diff changeset
2912 if (info->_scope_debug_info == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2913 // compute debug information
1819
f02a8bbe6ed4 6986046: C1 valuestack cleanup
roland
parents: 1816
diff changeset
2914 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
2915 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2916 // 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
2917 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
2918 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2919 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2920
a61af66fc99e Initial load
duke
parents:
diff changeset
2921
a61af66fc99e Initial load
duke
parents:
diff changeset
2922 void LinearScan::assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2923 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
2924 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2925 bool has_dead = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2926
a61af66fc99e Initial load
duke
parents:
diff changeset
2927 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2928 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
2929 if (op == NULL) { // this can happen when spill-moves are removed in eliminate_spill_moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2930 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2931 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
2932 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2933 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2934
a61af66fc99e Initial load
duke
parents:
diff changeset
2935 // visit instruction to get list of operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2936 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2937
a61af66fc99e Initial load
duke
parents:
diff changeset
2938 // iterate all modes of the visitor and process all virtual operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2939 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2940 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2941 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2942 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2943 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2944 visitor.set_opr_at(mode, k, color_lir_opr(opr, op_id, mode));
a61af66fc99e Initial load
duke
parents:
diff changeset
2945 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2946 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2948
a61af66fc99e Initial load
duke
parents:
diff changeset
2949 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2950 // exception handling
a61af66fc99e Initial load
duke
parents:
diff changeset
2951 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2952 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
2953 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2954 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2955 XHandler* handler = xhandlers->handler_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2956 if (handler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2957 assign_reg_num(handler->entry_code()->instructions_list(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2958 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2959 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2960 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2961 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2962 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2963
a61af66fc99e Initial load
duke
parents:
diff changeset
2964 // compute oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2965 assert(iw != NULL, "needed for compute_oop_map");
a61af66fc99e Initial load
duke
parents:
diff changeset
2966 compute_oop_map(iw, visitor, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2967
a61af66fc99e Initial load
duke
parents:
diff changeset
2968 // compute debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2969 if (!use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2970 // compute debug information if fpu stack allocation is not needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2971 // when fpu stack allocation is needed, the debug information can not
a61af66fc99e Initial load
duke
parents:
diff changeset
2972 // be computed here because the exact location of fpu operands is not known
a61af66fc99e Initial load
duke
parents:
diff changeset
2973 // -> debug information is created inside the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
2974 int n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2975 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2976 compute_debug_info(visitor.info_at(k), op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2977 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2978 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2979 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2980
a61af66fc99e Initial load
duke
parents:
diff changeset
2981 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2982 // make sure we haven't made the op invalid.
a61af66fc99e Initial load
duke
parents:
diff changeset
2983 op->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2984 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2985
a61af66fc99e Initial load
duke
parents:
diff changeset
2986 // remove useless moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2987 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2988 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2989 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2990 LIR_Opr src = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2991 LIR_Opr dst = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2992 if (dst == src ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2993 !dst->is_pointer() && !src->is_pointer() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2994 src->is_same_register(dst)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2995 instructions->at_put(j, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2996 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2997 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2998 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2999 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3000
a61af66fc99e Initial load
duke
parents:
diff changeset
3001 if (has_dead) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3002 // iterate all instructions of the block and remove all null-values.
a61af66fc99e Initial load
duke
parents:
diff changeset
3003 int insert_point = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3004 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3005 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3006 if (op != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3007 if (insert_point != j) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3008 instructions->at_put(insert_point, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3009 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3010 insert_point++;
a61af66fc99e Initial load
duke
parents:
diff changeset
3011 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3012 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3013 instructions->truncate(insert_point);
a61af66fc99e Initial load
duke
parents:
diff changeset
3014 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3015 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3016
a61af66fc99e Initial load
duke
parents:
diff changeset
3017 void LinearScan::assign_reg_num() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3018 TIME_LINEAR_SCAN(timer_assign_reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
3019
a61af66fc99e Initial load
duke
parents:
diff changeset
3020 init_compute_debug_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
3021 IntervalWalker* iw = init_compute_oop_maps();
a61af66fc99e Initial load
duke
parents:
diff changeset
3022
a61af66fc99e Initial load
duke
parents:
diff changeset
3023 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3024 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3025 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3026 assign_reg_num(block->lir()->instructions_list(), iw);
a61af66fc99e Initial load
duke
parents:
diff changeset
3027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3028 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3029
a61af66fc99e Initial load
duke
parents:
diff changeset
3030
a61af66fc99e Initial load
duke
parents:
diff changeset
3031 void LinearScan::do_linear_scan() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3032 NOT_PRODUCT(_total_timer.begin_method());
a61af66fc99e Initial load
duke
parents:
diff changeset
3033
a61af66fc99e Initial load
duke
parents:
diff changeset
3034 number_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
3035
a61af66fc99e Initial load
duke
parents:
diff changeset
3036 NOT_PRODUCT(print_lir(1, "Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3037
a61af66fc99e Initial load
duke
parents:
diff changeset
3038 compute_local_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
3039 compute_global_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
3040 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3041
a61af66fc99e Initial load
duke
parents:
diff changeset
3042 build_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3043 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3044 sort_intervals_before_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
3045
a61af66fc99e Initial load
duke
parents:
diff changeset
3046 NOT_PRODUCT(print_intervals("Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3047 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_before_alloc));
a61af66fc99e Initial load
duke
parents:
diff changeset
3048
a61af66fc99e Initial load
duke
parents:
diff changeset
3049 allocate_registers();
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 resolve_data_flow();
a61af66fc99e Initial load
duke
parents:
diff changeset
3053 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3054 resolve_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3055 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3056 // fill in number of spill slots into frame_map
a61af66fc99e Initial load
duke
parents:
diff changeset
3057 propagate_spill_slots();
a61af66fc99e Initial load
duke
parents:
diff changeset
3058 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3059
a61af66fc99e Initial load
duke
parents:
diff changeset
3060 NOT_PRODUCT(print_intervals("After Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3061 NOT_PRODUCT(print_lir(2, "LIR after register allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3062
a61af66fc99e Initial load
duke
parents:
diff changeset
3063 sort_intervals_after_allocation();
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3064
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3065 DEBUG_ONLY(verify());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3066
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3067 eliminate_spill_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
3068 assign_reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
3069 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3070
a61af66fc99e Initial load
duke
parents:
diff changeset
3071 NOT_PRODUCT(print_lir(2, "LIR after assignment of register numbers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3072 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_after_asign));
a61af66fc99e Initial load
duke
parents:
diff changeset
3073
a61af66fc99e Initial load
duke
parents:
diff changeset
3074 { TIME_LINEAR_SCAN(timer_allocate_fpu_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
3075
a61af66fc99e Initial load
duke
parents:
diff changeset
3076 if (use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3077 allocate_fpu_stack(); // Only has effect on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
3078 NOT_PRODUCT(print_lir(2, "LIR after FPU stack allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3079 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3080 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3081
a61af66fc99e Initial load
duke
parents:
diff changeset
3082 { TIME_LINEAR_SCAN(timer_optimize_lir);
a61af66fc99e Initial load
duke
parents:
diff changeset
3083
a61af66fc99e Initial load
duke
parents:
diff changeset
3084 EdgeMoveOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3085 ControlFlowOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3086 // check that cfg is still correct after optimizations
a61af66fc99e Initial load
duke
parents:
diff changeset
3087 ir()->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
3088 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3089
a61af66fc99e Initial load
duke
parents:
diff changeset
3090 NOT_PRODUCT(print_lir(1, "Before Code Generation", false));
a61af66fc99e Initial load
duke
parents:
diff changeset
3091 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final));
a61af66fc99e Initial load
duke
parents:
diff changeset
3092 NOT_PRODUCT(_total_timer.end_method(this));
a61af66fc99e Initial load
duke
parents:
diff changeset
3093 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3094
a61af66fc99e Initial load
duke
parents:
diff changeset
3095
a61af66fc99e Initial load
duke
parents:
diff changeset
3096 // ********** Printing functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3097
a61af66fc99e Initial load
duke
parents:
diff changeset
3098 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3099
a61af66fc99e Initial load
duke
parents:
diff changeset
3100 void LinearScan::print_timers(double total) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3101 _total_timer.print(total);
a61af66fc99e Initial load
duke
parents:
diff changeset
3102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3103
a61af66fc99e Initial load
duke
parents:
diff changeset
3104 void LinearScan::print_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3105 _stat_before_alloc.print("before allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3106 _stat_after_asign.print("after assignment of register");
a61af66fc99e Initial load
duke
parents:
diff changeset
3107 _stat_final.print("after optimization");
a61af66fc99e Initial load
duke
parents:
diff changeset
3108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3109
a61af66fc99e Initial load
duke
parents:
diff changeset
3110 void LinearScan::print_bitmap(BitMap& b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3111 for (unsigned int i = 0; i < b.size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3112 if (b.at(i)) tty->print("%d ", i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3114 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3116
a61af66fc99e Initial load
duke
parents:
diff changeset
3117 void LinearScan::print_intervals(const char* label) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3118 if (TraceLinearScanLevel >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3119 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3120 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3121 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3122
a61af66fc99e Initial load
duke
parents:
diff changeset
3123 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3124 Interval* interval = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3125 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3126 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
3127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3129
a61af66fc99e Initial load
duke
parents:
diff changeset
3130 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3131 tty->print_cr("--- Basic Blocks ---");
a61af66fc99e Initial load
duke
parents:
diff changeset
3132 for (i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3133 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3134 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
3135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3136 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3137 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3139
a61af66fc99e Initial load
duke
parents:
diff changeset
3140 if (PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3141 CFGPrinter::print_intervals(&_intervals, label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3143 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3144
a61af66fc99e Initial load
duke
parents:
diff changeset
3145 void LinearScan::print_lir(int level, const char* label, bool hir_valid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3146 if (TraceLinearScanLevel >= level) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3147 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3148 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3149 print_LIR(ir()->linear_scan_order());
a61af66fc99e Initial load
duke
parents:
diff changeset
3150 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3152
a61af66fc99e Initial load
duke
parents:
diff changeset
3153 if (level == 1 && PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3154 CFGPrinter::print_cfg(ir()->linear_scan_order(), label, hir_valid, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3157
a61af66fc99e Initial load
duke
parents:
diff changeset
3158 #endif //PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3159
a61af66fc99e Initial load
duke
parents:
diff changeset
3160
a61af66fc99e Initial load
duke
parents:
diff changeset
3161 // ********** verification functions for allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
3162 // (check that all intervals have a correct register and that no registers are overwritten)
a61af66fc99e Initial load
duke
parents:
diff changeset
3163 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3164
a61af66fc99e Initial load
duke
parents:
diff changeset
3165 void LinearScan::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3166 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying intervals ******************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3167 verify_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3168
a61af66fc99e Initial load
duke
parents:
diff changeset
3169 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that no oops are in fixed intervals ****************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3170 verify_no_oops_in_fixed_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3171
a61af66fc99e Initial load
duke
parents:
diff changeset
3172 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that unpinned constants are not alive across block boundaries"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3173 verify_constants();
a61af66fc99e Initial load
duke
parents:
diff changeset
3174
a61af66fc99e Initial load
duke
parents:
diff changeset
3175 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying register allocation ********************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3176 verify_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3177
a61af66fc99e Initial load
duke
parents:
diff changeset
3178 TRACE_LINEAR_SCAN(2, tty->print_cr("********* no errors found **********************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3179 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3180
a61af66fc99e Initial load
duke
parents:
diff changeset
3181 void LinearScan::verify_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3182 int len = interval_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3183 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3184
a61af66fc99e Initial load
duke
parents:
diff changeset
3185 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3186 Interval* i1 = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3187 if (i1 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3188
a61af66fc99e Initial load
duke
parents:
diff changeset
3189 i1->check_split_children();
a61af66fc99e Initial load
duke
parents:
diff changeset
3190
a61af66fc99e Initial load
duke
parents:
diff changeset
3191 if (i1->reg_num() != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3192 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
3193 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3195
a61af66fc99e Initial load
duke
parents:
diff changeset
3196 if (i1->reg_num() >= LIR_OprDesc::vreg_base && i1->type() == T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3197 tty->print_cr("Interval %d has no type assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3198 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3200
a61af66fc99e Initial load
duke
parents:
diff changeset
3201 if (i1->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3202 tty->print_cr("Interval %d has no register assigned", i1->reg_num()); 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->assigned_reg() == i1->assigned_regHi()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3207 tty->print_cr("Interval %d: low and high register equal", 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 (!is_processed_reg_num(i1->assigned_reg())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3212 tty->print_cr("Can not have an Interval for an ignored register"); 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->first() == Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3217 tty->print_cr("Interval %d has no Range", 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 for (Range* r = i1->first(); r != Range::end(); r = r->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3222 if (r->from() >= r->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3223 tty->print_cr("Interval %d has zero length range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3224 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3227
a61af66fc99e Initial load
duke
parents:
diff changeset
3228 for (int j = i + 1; j < len; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3229 Interval* i2 = interval_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3230 if (i2 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3231
a61af66fc99e Initial load
duke
parents:
diff changeset
3232 // special intervals that are created in MoveResolver
a61af66fc99e Initial load
duke
parents:
diff changeset
3233 // -> ignore them because the range information has no meaning there
a61af66fc99e Initial load
duke
parents:
diff changeset
3234 if (i1->from() == 1 && i1->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3235 if (i2->from() == 1 && i2->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3236
a61af66fc99e Initial load
duke
parents:
diff changeset
3237 int r1 = i1->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3238 int r1Hi = i1->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3239 int r2 = i2->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3240 int r2Hi = i2->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3241 if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3242 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
3243 i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3244 i2->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3245 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3247 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3248 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3249
a61af66fc99e Initial load
duke
parents:
diff changeset
3250 assert(has_error == false, "register allocation invalid");
a61af66fc99e Initial load
duke
parents:
diff changeset
3251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3252
a61af66fc99e Initial load
duke
parents:
diff changeset
3253
a61af66fc99e Initial load
duke
parents:
diff changeset
3254 void LinearScan::verify_no_oops_in_fixed_intervals() {
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3255 Interval* fixed_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3256 Interval* other_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3257 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
3258
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3259 // 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
3260 // with a high operation id
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3261 other_intervals = new Interval(any_reg);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3262 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
3263 IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3264
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3265 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3266 for (int i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3267 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3268
a61af66fc99e Initial load
duke
parents:
diff changeset
3269 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
3270
a61af66fc99e Initial load
duke
parents:
diff changeset
3271 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3272 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3273 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
3274
a61af66fc99e Initial load
duke
parents:
diff changeset
3275 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3276
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3277 if (visitor.info_count() > 0) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3278 iw->walk_before(op->id());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3279 bool check_live = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3280 if (op->code() == lir_move) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3281 LIR_Op1* move = (LIR_Op1*)op;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3282 check_live = (move->patch_code() == lir_patch_none);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3283 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3284 LIR_OpBranch* branch = op->as_OpBranch();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3285 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
3286 // 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
3287 // exception stub will never return to normal control flow.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3288 check_live = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3289 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3290
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3291 // 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
3292 // oopmap since we can't handle that correctly.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3293 if (check_live) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3294 for (Interval* interval = iw->active_first(fixedKind);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3295 interval != Interval::end();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3296 interval = interval->next()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3297 if (interval->current_to() > op->id() + 1) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3298 // 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
3299 // that this interval represents some value that's
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3300 // 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
3301 bool ok = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3302 for_each_visitor_mode(mode) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3303 int n = visitor.opr_count(mode);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3304 for (int k = 0; k < n; k++) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3305 LIR_Opr opr = visitor.opr_at(mode, k);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3306 if (opr->is_fixed_cpu()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3307 if (interval_at(reg_num(opr)) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3308 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3309 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3310 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3311 int hi = reg_numHi(opr);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3312 if (hi != -1 && interval_at(hi) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3313 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3314 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3315 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3316 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3317 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3318 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3319 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
3320 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3321 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3322 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3323 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3324
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3325 // oop-maps at calls do not contain registers, so check is not needed
a61af66fc99e Initial load
duke
parents:
diff changeset
3326 if (!visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3327
a61af66fc99e Initial load
duke
parents:
diff changeset
3328 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3329 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3330 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3331 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
3332
a61af66fc99e Initial load
duke
parents:
diff changeset
3333 if (opr->is_fixed_cpu() && opr->is_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3334 // operand is a non-virtual cpu register and contains an oop
a61af66fc99e Initial load
duke
parents:
diff changeset
3335 TRACE_LINEAR_SCAN(4, op->print_on(tty); tty->print("checking operand "); opr->print(); tty->cr());
a61af66fc99e Initial load
duke
parents:
diff changeset
3336
a61af66fc99e Initial load
duke
parents:
diff changeset
3337 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3338 assert(interval != NULL, "no interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
3339
a61af66fc99e Initial load
duke
parents:
diff changeset
3340 if (mode == LIR_OpVisitState::inputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3341 if (interval->to() >= op_id + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3342 assert(interval->to() < op_id + 2 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
3343 interval->has_hole_between(op_id, op_id + 2),
a61af66fc99e Initial load
duke
parents:
diff changeset
3344 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3346 } else if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3347 if (interval->from() <= op_id - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3348 assert(interval->has_hole_between(op_id - 1, op_id),
a61af66fc99e Initial load
duke
parents:
diff changeset
3349 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3350 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3352 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3353 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3354 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3355 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3357 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3359
a61af66fc99e Initial load
duke
parents:
diff changeset
3360
a61af66fc99e Initial load
duke
parents:
diff changeset
3361 void LinearScan::verify_constants() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3362 int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
3363 int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
3364 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3365
a61af66fc99e Initial load
duke
parents:
diff changeset
3366 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3367 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3368 BitMap live_at_edge = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
3369
a61af66fc99e Initial load
duke
parents:
diff changeset
3370 // 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
3371 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
3372 TRACE_LINEAR_SCAN(4, tty->print("checking interval %d of block B%d", r, block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3373
a61af66fc99e Initial load
duke
parents:
diff changeset
3374 Value value = gen()->instruction_for_vreg(r);
a61af66fc99e Initial load
duke
parents:
diff changeset
3375
a61af66fc99e Initial load
duke
parents:
diff changeset
3376 assert(value != NULL, "all intervals live across block boundaries must have Value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3377 assert(value->operand()->is_register() && value->operand()->is_virtual(), "value must have virtual operand");
a61af66fc99e Initial load
duke
parents:
diff changeset
3378 assert(value->operand()->vreg_number() == r, "register number must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
3379 // 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
3380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3383
a61af66fc99e Initial load
duke
parents:
diff changeset
3384
a61af66fc99e Initial load
duke
parents:
diff changeset
3385 class RegisterVerifier: public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
3386 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
3387 LinearScan* _allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
3388 BlockList _work_list; // all blocks that must be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3389 IntervalsList _saved_states; // saved information of previous check
a61af66fc99e Initial load
duke
parents:
diff changeset
3390
a61af66fc99e Initial load
duke
parents:
diff changeset
3391 // simplified access to methods of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
3392 Compilation* compilation() const { return _allocator->compilation(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3393 Interval* interval_at(int reg_num) const { return _allocator->interval_at(reg_num); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3394 int reg_num(LIR_Opr opr) const { return _allocator->reg_num(opr); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3395
a61af66fc99e Initial load
duke
parents:
diff changeset
3396 // currently, only registers are processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3397 int state_size() { return LinearScan::nof_regs; }
a61af66fc99e Initial load
duke
parents:
diff changeset
3398
a61af66fc99e Initial load
duke
parents:
diff changeset
3399 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
3400 IntervalList* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3401 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
3402 void add_to_work_list(BlockBegin* block) { if (!_work_list.contains(block)) _work_list.append(block); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3403
a61af66fc99e Initial load
duke
parents:
diff changeset
3404 // helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3405 IntervalList* copy(IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3406 void state_put(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3407 bool check_state(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3408
a61af66fc99e Initial load
duke
parents:
diff changeset
3409 void process_block(BlockBegin* block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3410 void process_xhandler(XHandler* xhandler, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3411 void process_successor(BlockBegin* block, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3412 void process_operations(LIR_List* ops, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3413
a61af66fc99e Initial load
duke
parents:
diff changeset
3414 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
3415 RegisterVerifier(LinearScan* allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3416 : _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3417 , _work_list(16)
a61af66fc99e Initial load
duke
parents:
diff changeset
3418 , _saved_states(BlockBegin::number_of_blocks(), NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
3419 { }
a61af66fc99e Initial load
duke
parents:
diff changeset
3420
a61af66fc99e Initial load
duke
parents:
diff changeset
3421 void verify(BlockBegin* start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3422 };
a61af66fc99e Initial load
duke
parents:
diff changeset
3423
a61af66fc99e Initial load
duke
parents:
diff changeset
3424
a61af66fc99e Initial load
duke
parents:
diff changeset
3425 // entry function from LinearScan that starts the verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3426 void LinearScan::verify_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3427 RegisterVerifier verifier(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
3428 verifier.verify(block_at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
3429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3430
a61af66fc99e Initial load
duke
parents:
diff changeset
3431
a61af66fc99e Initial load
duke
parents:
diff changeset
3432 void RegisterVerifier::verify(BlockBegin* start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3433 // setup input registers (method arguments) for first block
a61af66fc99e Initial load
duke
parents:
diff changeset
3434 IntervalList* input_state = new IntervalList(state_size(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3435 CallingConvention* args = compilation()->frame_map()->incoming_arguments();
a61af66fc99e Initial load
duke
parents:
diff changeset
3436 for (int n = 0; n < args->length(); n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3437 LIR_Opr opr = args->at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
3438 if (opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3439 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3440
a61af66fc99e Initial load
duke
parents:
diff changeset
3441 if (interval->assigned_reg() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3442 input_state->at_put(interval->assigned_reg(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3443 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3444 if (interval->assigned_regHi() != LinearScan::any_reg && interval->assigned_regHi() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3445 input_state->at_put(interval->assigned_regHi(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3449
a61af66fc99e Initial load
duke
parents:
diff changeset
3450 set_state_for_block(start, input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3451 add_to_work_list(start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3452
a61af66fc99e Initial load
duke
parents:
diff changeset
3453 // main loop for verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3454 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
3455 BlockBegin* block = _work_list.at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3456 _work_list.remove_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3457
a61af66fc99e Initial load
duke
parents:
diff changeset
3458 process_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3459 } while (!_work_list.is_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3461
a61af66fc99e Initial load
duke
parents:
diff changeset
3462 void RegisterVerifier::process_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3463 TRACE_LINEAR_SCAN(2, tty->cr(); tty->print_cr("process_block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3464
a61af66fc99e Initial load
duke
parents:
diff changeset
3465 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3466 IntervalList* input_state = copy(state_for_block(block));
a61af66fc99e Initial load
duke
parents:
diff changeset
3467
a61af66fc99e Initial load
duke
parents:
diff changeset
3468 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3469 tty->print_cr("Input-State of intervals:");
a61af66fc99e Initial load
duke
parents:
diff changeset
3470 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
3471 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3472 if (input_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3473 tty->print(" %4d", input_state->at(i)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3474 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3475 tty->print(" __");
a61af66fc99e Initial load
duke
parents:
diff changeset
3476 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3477 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3478 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3479 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3481
a61af66fc99e Initial load
duke
parents:
diff changeset
3482 // process all operations of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3483 process_operations(block->lir(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3484
a61af66fc99e Initial load
duke
parents:
diff changeset
3485 // iterate all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
3486 for (int i = 0; i < block->number_of_sux(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3487 process_successor(block->sux_at(i), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3490
a61af66fc99e Initial load
duke
parents:
diff changeset
3491 void RegisterVerifier::process_xhandler(XHandler* xhandler, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3492 TRACE_LINEAR_SCAN(2, tty->print_cr("process_xhandler B%d", xhandler->entry_block()->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3493
a61af66fc99e Initial load
duke
parents:
diff changeset
3494 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3495 input_state = copy(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3496
a61af66fc99e Initial load
duke
parents:
diff changeset
3497 if (xhandler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3498 process_operations(xhandler->entry_code(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3499 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3500 process_successor(xhandler->entry_block(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3502
a61af66fc99e Initial load
duke
parents:
diff changeset
3503 void RegisterVerifier::process_successor(BlockBegin* block, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3504 IntervalList* saved_state = state_for_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3505
a61af66fc99e Initial load
duke
parents:
diff changeset
3506 if (saved_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3507 // this block was already processed before.
a61af66fc99e Initial load
duke
parents:
diff changeset
3508 // check if new input_state is consistent with saved_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3509
a61af66fc99e Initial load
duke
parents:
diff changeset
3510 bool saved_state_correct = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3511 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3512 if (input_state->at(i) != saved_state->at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3513 // current input_state and previous saved_state assume a different
a61af66fc99e Initial load
duke
parents:
diff changeset
3514 // interval in this register -> assume that this register is invalid
a61af66fc99e Initial load
duke
parents:
diff changeset
3515 if (saved_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3516 // invalidate old calculation only if it assumed that
a61af66fc99e Initial load
duke
parents:
diff changeset
3517 // register was valid. when the register was already invalid,
a61af66fc99e Initial load
duke
parents:
diff changeset
3518 // then the old calculation was correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
3519 saved_state_correct = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3520 saved_state->at_put(i, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3521
a61af66fc99e Initial load
duke
parents:
diff changeset
3522 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
3523 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3524 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3526
a61af66fc99e Initial load
duke
parents:
diff changeset
3527 if (saved_state_correct) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3528 // already processed block with correct input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3529 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
3530 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3531 // must re-visit this block
a61af66fc99e Initial load
duke
parents:
diff changeset
3532 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
3533 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3535
a61af66fc99e Initial load
duke
parents:
diff changeset
3536 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3537 // block was not processed before, so set initial input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3538 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: initial visit", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3539
a61af66fc99e Initial load
duke
parents:
diff changeset
3540 set_state_for_block(block, copy(input_state));
a61af66fc99e Initial load
duke
parents:
diff changeset
3541 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3543 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3544
a61af66fc99e Initial load
duke
parents:
diff changeset
3545
a61af66fc99e Initial load
duke
parents:
diff changeset
3546 IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3547 IntervalList* copy_state = new IntervalList(input_state->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
3548 copy_state->push_all(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3549 return copy_state;
a61af66fc99e Initial load
duke
parents:
diff changeset
3550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3551
a61af66fc99e Initial load
duke
parents:
diff changeset
3552 void RegisterVerifier::state_put(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3553 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3554 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3555 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = %d", reg, interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3556 } else if (input_state->at(reg) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3557 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = NULL", reg));
a61af66fc99e Initial load
duke
parents:
diff changeset
3558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3559
a61af66fc99e Initial load
duke
parents:
diff changeset
3560 input_state->at_put(reg, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3561 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3563
a61af66fc99e Initial load
duke
parents:
diff changeset
3564 bool RegisterVerifier::check_state(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3565 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3566 if (input_state->at(reg) != interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3567 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
3568 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3569 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3571 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3573
a61af66fc99e Initial load
duke
parents:
diff changeset
3574 void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3575 // visit all instructions of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3576 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3577 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3578
a61af66fc99e Initial load
duke
parents:
diff changeset
3579 for (int i = 0; i < ops->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3580 LIR_Op* op = ops->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3581 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3582
a61af66fc99e Initial load
duke
parents:
diff changeset
3583 TRACE_LINEAR_SCAN(4, op->print_on(tty));
a61af66fc99e Initial load
duke
parents:
diff changeset
3584
a61af66fc99e Initial load
duke
parents:
diff changeset
3585 // check if input operands are correct
a61af66fc99e Initial load
duke
parents:
diff changeset
3586 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3587 int n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3588 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3589 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3590 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3591 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3592 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3593 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3595
a61af66fc99e Initial load
duke
parents:
diff changeset
3596 has_error |= check_state(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3597 has_error |= check_state(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3598
a61af66fc99e Initial load
duke
parents:
diff changeset
3599 // When an operand is marked with is_last_use, then the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
3600 // removes the register from the fpu stack -> the register contains no value
a61af66fc99e Initial load
duke
parents:
diff changeset
3601 if (opr->is_last_use()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3602 state_put(input_state, interval->assigned_reg(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3603 state_put(input_state, interval->assigned_regHi(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3605 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3606 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3607
a61af66fc99e Initial load
duke
parents:
diff changeset
3608 // invalidate all caller save registers at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
3609 if (visitor.has_call()) {
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
3610 for (j = 0; j < FrameMap::nof_caller_save_cpu_regs(); j++) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3611 state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3612 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3613 for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3614 state_put(input_state, reg_num(FrameMap::caller_save_fpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3615 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3616
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
3617 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3618 for (j = 0; j < FrameMap::nof_caller_save_xmm_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3619 state_put(input_state, reg_num(FrameMap::caller_save_xmm_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3621 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3623
a61af66fc99e Initial load
duke
parents:
diff changeset
3624 // process xhandler before output and temp operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3625 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
3626 n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
3627 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3628 process_xhandler(xhandlers->handler_at(k), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3629 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3630
a61af66fc99e Initial load
duke
parents:
diff changeset
3631 // 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
3632 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3633 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3634 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3635 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3636 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3637 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3638 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3640
a61af66fc99e Initial load
duke
parents:
diff changeset
3641 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3642 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3643 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3645
a61af66fc99e Initial load
duke
parents:
diff changeset
3646 // set output operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3647 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3648 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3649 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3650 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3651 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3652 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3653 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3655
a61af66fc99e Initial load
duke
parents:
diff changeset
3656 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3657 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3658 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3659 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3660 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3661 assert(has_error == false, "Error in register allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3662 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3663
a61af66fc99e Initial load
duke
parents:
diff changeset
3664 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3665
a61af66fc99e Initial load
duke
parents:
diff changeset
3666
a61af66fc99e Initial load
duke
parents:
diff changeset
3667
a61af66fc99e Initial load
duke
parents:
diff changeset
3668 // **** Implementation of MoveResolver ******************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3669
a61af66fc99e Initial load
duke
parents:
diff changeset
3670 MoveResolver::MoveResolver(LinearScan* allocator) :
a61af66fc99e Initial load
duke
parents:
diff changeset
3671 _allocator(allocator),
a61af66fc99e Initial load
duke
parents:
diff changeset
3672 _multiple_reads_allowed(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
3673 _mapping_from(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3674 _mapping_from_opr(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3675 _mapping_to(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3676 _insert_list(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
3677 _insert_idx(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
3678 _insertion_buffer()
a61af66fc99e Initial load
duke
parents:
diff changeset
3679 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3680 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3681 _register_blocked[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3682 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3683 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3684 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3685
a61af66fc99e Initial load
duke
parents:
diff changeset
3686
a61af66fc99e Initial load
duke
parents:
diff changeset
3687 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3688
a61af66fc99e Initial load
duke
parents:
diff changeset
3689 void MoveResolver::check_empty() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3690 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
3691 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3692 assert(register_blocked(i) == 0, "register map must be empty before and after processing");
a61af66fc99e Initial load
duke
parents:
diff changeset
3693 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3694 assert(_multiple_reads_allowed == false, "must have default value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3695 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3696
a61af66fc99e Initial load
duke
parents:
diff changeset
3697 void MoveResolver::verify_before_resolve() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3698 assert(_mapping_from.length() == _mapping_from_opr.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3699 assert(_mapping_from.length() == _mapping_to.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3700 assert(_insert_list != NULL && _insert_idx != -1, "insert position not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
3701
a61af66fc99e Initial load
duke
parents:
diff changeset
3702 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3703 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3704 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3705 for (j = i + 1; j < _mapping_from.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3706 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
3707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3710
a61af66fc99e Initial load
duke
parents:
diff changeset
3711 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3712 for (j = i + 1; j < _mapping_to.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3713 assert(_mapping_to.at(i) != _mapping_to.at(j), "cannot write to same interval twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3714 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3716
a61af66fc99e Initial load
duke
parents:
diff changeset
3717
a61af66fc99e Initial load
duke
parents:
diff changeset
3718 BitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
3719 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3720 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3721 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3722 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3723 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3724 assert(!used_regs.at(it->assigned_reg()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3725 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3726
a61af66fc99e Initial load
duke
parents:
diff changeset
3727 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3728 assert(!used_regs.at(it->assigned_regHi()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3729 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3730 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3731 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3732 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3733 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3734
a61af66fc99e Initial load
duke
parents:
diff changeset
3735 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3736 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3737 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3738 assert(!used_regs.at(it->assigned_reg()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3739 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3740
a61af66fc99e Initial load
duke
parents:
diff changeset
3741 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3742 assert(!used_regs.at(it->assigned_regHi()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3743 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3744 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3745 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3746
a61af66fc99e Initial load
duke
parents:
diff changeset
3747 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3748 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3749 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3750 if (it != NULL && it->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3751 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3752 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3753 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3754 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3755 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3756 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
3757 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3758 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3759
a61af66fc99e Initial load
duke
parents:
diff changeset
3760 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3761
a61af66fc99e Initial load
duke
parents:
diff changeset
3762
a61af66fc99e Initial load
duke
parents:
diff changeset
3763 // mark assigned_reg and assigned_regHi of the interval as blocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3764 void MoveResolver::block_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3765 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3766 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3767 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3768 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3769 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3770 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3771 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3772 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3773 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3774 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3776
a61af66fc99e Initial load
duke
parents:
diff changeset
3777 // mark assigned_reg and assigned_regHi of the interval as unblocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3778 void MoveResolver::unblock_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3779 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3780 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3781 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3782 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3783 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3784 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3785 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3786 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3787 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3788 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3789 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3790
a61af66fc99e Initial load
duke
parents:
diff changeset
3791 // 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
3792 bool MoveResolver::save_to_process_move(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3793 int from_reg = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3794 int from_regHi = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3795 if (from != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3796 from_reg = from->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3797 from_regHi = from->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3799
a61af66fc99e Initial load
duke
parents:
diff changeset
3800 int reg = to->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3801 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3802 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3803 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3804 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3805 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3806 reg = to->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3807 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3808 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3809 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3810 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3812
a61af66fc99e Initial load
duke
parents:
diff changeset
3813 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3815
a61af66fc99e Initial load
duke
parents:
diff changeset
3816
a61af66fc99e Initial load
duke
parents:
diff changeset
3817 void MoveResolver::create_insertion_buffer(LIR_List* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3818 assert(!_insertion_buffer.initialized(), "overwriting existing buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3819 _insertion_buffer.init(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3821
a61af66fc99e Initial load
duke
parents:
diff changeset
3822 void MoveResolver::append_insertion_buffer() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3823 if (_insertion_buffer.initialized()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3824 _insertion_buffer.lir_list()->append(&_insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
3825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3826 assert(!_insertion_buffer.initialized(), "must be uninitialized now");
a61af66fc99e Initial load
duke
parents:
diff changeset
3827
a61af66fc99e Initial load
duke
parents:
diff changeset
3828 _insert_list = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
3829 _insert_idx = -1;
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::insert_move(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3833 assert(from_interval->reg_num() != to_interval->reg_num(), "from and to interval equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3834 assert(from_interval->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3835 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3836 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3837
a61af66fc99e Initial load
duke
parents:
diff changeset
3838 LIR_Opr from_opr = LIR_OprFact::virtual_register(from_interval->reg_num(), from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3839 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3840
a61af66fc99e Initial load
duke
parents:
diff changeset
3841 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3842 // the last_use flag is an optimization for FPU stack allocation. When the same
a61af66fc99e Initial load
duke
parents:
diff changeset
3843 // input interval is used in more than one move, then it is too difficult to determine
a61af66fc99e Initial load
duke
parents:
diff changeset
3844 // if this move is really the last use.
a61af66fc99e Initial load
duke
parents:
diff changeset
3845 from_opr = from_opr->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
3846 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3847 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3848
a61af66fc99e Initial load
duke
parents:
diff changeset
3849 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
3850 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3851
a61af66fc99e Initial load
duke
parents:
diff changeset
3852 void MoveResolver::insert_move(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3853 assert(from_opr->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3854 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3855 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3856
a61af66fc99e Initial load
duke
parents:
diff changeset
3857 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3858 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3859
a61af66fc99e Initial load
duke
parents:
diff changeset
3860 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
3861 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3862
a61af66fc99e Initial load
duke
parents:
diff changeset
3863
a61af66fc99e Initial load
duke
parents:
diff changeset
3864 void MoveResolver::resolve_mappings() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3865 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
3866 DEBUG_ONLY(verify_before_resolve());
a61af66fc99e Initial load
duke
parents:
diff changeset
3867
a61af66fc99e Initial load
duke
parents:
diff changeset
3868 // Block all registers that are used as input operands of a move.
a61af66fc99e Initial load
duke
parents:
diff changeset
3869 // When a register is blocked, no move to this register is emitted.
a61af66fc99e Initial load
duke
parents:
diff changeset
3870 // This is necessary for detecting cycles in moves.
a61af66fc99e Initial load
duke
parents:
diff changeset
3871 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3872 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3873 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3874 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3875 block_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3876 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3877 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3878
a61af66fc99e Initial load
duke
parents:
diff changeset
3879 int spill_candidate = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3880 while (_mapping_from.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3881 bool processed_interval = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3882
a61af66fc99e Initial load
duke
parents:
diff changeset
3883 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3884 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3885 Interval* to_interval = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3886
a61af66fc99e Initial load
duke
parents:
diff changeset
3887 if (save_to_process_move(from_interval, to_interval)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3888 // this inverval can be processed because target is free
a61af66fc99e Initial load
duke
parents:
diff changeset
3889 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3890 insert_move(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3891 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3892 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3893 insert_move(_mapping_from_opr.at(i), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3894 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3895 _mapping_from.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3896 _mapping_from_opr.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3897 _mapping_to.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3898
a61af66fc99e Initial load
duke
parents:
diff changeset
3899 processed_interval = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3900 } else if (from_interval != NULL && from_interval->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3901 // this interval cannot be processed now because target is not free
a61af66fc99e Initial load
duke
parents:
diff changeset
3902 // it starts in a register, so it is a possible candidate for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
3903 spill_candidate = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3904 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3905 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3906
a61af66fc99e Initial load
duke
parents:
diff changeset
3907 if (!processed_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3908 // no move could be processed because there is a cycle in the move list
a61af66fc99e Initial load
duke
parents:
diff changeset
3909 // (e.g. r1 -> r2, r2 -> r1), so one interval must be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
3910 assert(spill_candidate != -1, "no interval in register for spilling found");
a61af66fc99e Initial load
duke
parents:
diff changeset
3911
a61af66fc99e Initial load
duke
parents:
diff changeset
3912 // create a new spill interval and assign a stack slot to it
a61af66fc99e Initial load
duke
parents:
diff changeset
3913 Interval* from_interval = _mapping_from.at(spill_candidate);
a61af66fc99e Initial load
duke
parents:
diff changeset
3914 Interval* spill_interval = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3915 spill_interval->set_type(from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3916
a61af66fc99e Initial load
duke
parents:
diff changeset
3917 // add a dummy range because real position is difficult to calculate
a61af66fc99e Initial load
duke
parents:
diff changeset
3918 // Note: this range is a special case when the integrity of the allocation is checked
a61af66fc99e Initial load
duke
parents:
diff changeset
3919 spill_interval->add_range(1, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3920
a61af66fc99e Initial load
duke
parents:
diff changeset
3921 // do not allocate a new spill slot for temporary interval, but
a61af66fc99e Initial load
duke
parents:
diff changeset
3922 // use spill slot assigned to from_interval. Otherwise moves from
a61af66fc99e Initial load
duke
parents:
diff changeset
3923 // one stack slot to another can happen (not allowed by LIR_Assembler
a61af66fc99e Initial load
duke
parents:
diff changeset
3924 int spill_slot = from_interval->canonical_spill_slot();
a61af66fc99e Initial load
duke
parents:
diff changeset
3925 if (spill_slot < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3926 spill_slot = allocator()->allocate_spill_slot(type2spill_size[spill_interval->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3927 from_interval->set_canonical_spill_slot(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3928 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3929 spill_interval->assign_reg(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3930 allocator()->append_interval(spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3931
a61af66fc99e Initial load
duke
parents:
diff changeset
3932 TRACE_LINEAR_SCAN(4, tty->print_cr("created new Interval %d for spilling", spill_interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3933
a61af66fc99e Initial load
duke
parents:
diff changeset
3934 // insert a move from register to stack and update the mapping
a61af66fc99e Initial load
duke
parents:
diff changeset
3935 insert_move(from_interval, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3936 _mapping_from.at_put(spill_candidate, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3937 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3939 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3940
a61af66fc99e Initial load
duke
parents:
diff changeset
3941 // reset to default value
a61af66fc99e Initial load
duke
parents:
diff changeset
3942 _multiple_reads_allowed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3943
a61af66fc99e Initial load
duke
parents:
diff changeset
3944 // check that all intervals have been processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3945 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3946 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3947
a61af66fc99e Initial load
duke
parents:
diff changeset
3948
a61af66fc99e Initial load
duke
parents:
diff changeset
3949 void MoveResolver::set_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3950 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
3951 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
3952
a61af66fc99e Initial load
duke
parents:
diff changeset
3953 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3954 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3955 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3956 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3957
a61af66fc99e Initial load
duke
parents:
diff changeset
3958 void MoveResolver::move_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3959 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
3960
a61af66fc99e Initial load
duke
parents:
diff changeset
3961 if (_insert_list != NULL && (insert_list != _insert_list || insert_idx != _insert_idx)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3962 // insert position changed -> resolve current mappings
a61af66fc99e Initial load
duke
parents:
diff changeset
3963 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3964 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3965
a61af66fc99e Initial load
duke
parents:
diff changeset
3966 if (insert_list != _insert_list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3967 // block changed -> append insertion_buffer because it is
a61af66fc99e Initial load
duke
parents:
diff changeset
3968 // bound to a specific block and create a new insertion_buffer
a61af66fc99e Initial load
duke
parents:
diff changeset
3969 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
3970 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3971 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3972
a61af66fc99e Initial load
duke
parents:
diff changeset
3973 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3974 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3975 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3976
a61af66fc99e Initial load
duke
parents:
diff changeset
3977 void MoveResolver::add_mapping(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3978 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
3979
a61af66fc99e Initial load
duke
parents:
diff changeset
3980 _mapping_from.append(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3981 _mapping_from_opr.append(LIR_OprFact::illegalOpr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3982 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3983 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3984
a61af66fc99e Initial load
duke
parents:
diff changeset
3985
a61af66fc99e Initial load
duke
parents:
diff changeset
3986 void MoveResolver::add_mapping(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3987 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
3988 assert(from_opr->is_constant(), "only for constants");
a61af66fc99e Initial load
duke
parents:
diff changeset
3989
a61af66fc99e Initial load
duke
parents:
diff changeset
3990 _mapping_from.append(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3991 _mapping_from_opr.append(from_opr);
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 void MoveResolver::resolve_and_append_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3996 if (has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3997 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3998 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3999 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
4000 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4001
a61af66fc99e Initial load
duke
parents:
diff changeset
4002
a61af66fc99e Initial load
duke
parents:
diff changeset
4003
a61af66fc99e Initial load
duke
parents:
diff changeset
4004 // **** Implementation of Range *************************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4005
a61af66fc99e Initial load
duke
parents:
diff changeset
4006 Range::Range(int from, int to, Range* next) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4007 _from(from),
a61af66fc99e Initial load
duke
parents:
diff changeset
4008 _to(to),
a61af66fc99e Initial load
duke
parents:
diff changeset
4009 _next(next)
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 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4014 Range* Range::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4015 void Range::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4016 _end = new (arena) Range(max_jint, max_jint, NULL);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4017 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4018
a61af66fc99e Initial load
duke
parents:
diff changeset
4019 int Range::intersects_at(Range* r2) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4020 const Range* r1 = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4021
a61af66fc99e Initial load
duke
parents:
diff changeset
4022 assert(r1 != NULL && r2 != NULL, "null ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
4023 assert(r1 != _end && r2 != _end, "empty ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
4024
a61af66fc99e Initial load
duke
parents:
diff changeset
4025 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
4026 if (r1->from() < r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4027 if (r1->to() <= r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4028 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4029 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4030 return r2->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4031 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4032 } else if (r2->from() < r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4033 if (r2->to() <= r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4034 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4035 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4036 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4038 } else { // r1->from() == r2->from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4039 if (r1->from() == r1->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4040 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4041 } else if (r2->from() == r2->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4042 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4043 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4044 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
4045 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4046 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4047 } while (true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4048 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4049
a61af66fc99e Initial load
duke
parents:
diff changeset
4050 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4051 void Range::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4052 out->print("[%d, %d[ ", _from, _to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4053 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4054 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4055
a61af66fc99e Initial load
duke
parents:
diff changeset
4056
a61af66fc99e Initial load
duke
parents:
diff changeset
4057
a61af66fc99e Initial load
duke
parents:
diff changeset
4058 // **** Implementation of Interval **********************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4059
a61af66fc99e Initial load
duke
parents:
diff changeset
4060 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4061 Interval* Interval::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4062 void Interval::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4063 Range::initialize(arena);
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4064 _end = new (arena) Interval(-1);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4065 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4066
a61af66fc99e Initial load
duke
parents:
diff changeset
4067 Interval::Interval(int reg_num) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4068 _reg_num(reg_num),
a61af66fc99e Initial load
duke
parents:
diff changeset
4069 _type(T_ILLEGAL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4070 _first(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4071 _use_pos_and_kinds(12),
a61af66fc99e Initial load
duke
parents:
diff changeset
4072 _current(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4073 _next(_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
4074 _state(invalidState),
a61af66fc99e Initial load
duke
parents:
diff changeset
4075 _assigned_reg(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4076 _assigned_regHi(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4077 _cached_to(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4078 _cached_opr(LIR_OprFact::illegalOpr),
a61af66fc99e Initial load
duke
parents:
diff changeset
4079 _cached_vm_reg(VMRegImpl::Bad()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4080 _split_children(0),
a61af66fc99e Initial load
duke
parents:
diff changeset
4081 _canonical_spill_slot(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4082 _insert_move_when_activated(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
4083 _register_hint(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4084 _spill_state(noDefinitionFound),
a61af66fc99e Initial load
duke
parents:
diff changeset
4085 _spill_definition_pos(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4086 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4087 _split_parent = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4088 _current_split_child = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4089 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4090
a61af66fc99e Initial load
duke
parents:
diff changeset
4091 int Interval::calc_to() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4092 assert(_first != Range::end(), "interval has no range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4093
a61af66fc99e Initial load
duke
parents:
diff changeset
4094 Range* r = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4095 while (r->next() != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4096 r = r->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4097 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4098 return r->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4099 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4100
a61af66fc99e Initial load
duke
parents:
diff changeset
4101
a61af66fc99e Initial load
duke
parents:
diff changeset
4102 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4103 // consistency check of split-children
a61af66fc99e Initial load
duke
parents:
diff changeset
4104 void Interval::check_split_children() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4105 if (_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4106 assert(is_split_parent(), "only split parents can have children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4107
a61af66fc99e Initial load
duke
parents:
diff changeset
4108 for (int i = 0; i < _split_children.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4109 Interval* i1 = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4110
a61af66fc99e Initial load
duke
parents:
diff changeset
4111 assert(i1->split_parent() == this, "not a split child of this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4112 assert(i1->type() == type(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4113 assert(i1->canonical_spill_slot() == canonical_spill_slot(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4114
a61af66fc99e Initial load
duke
parents:
diff changeset
4115 for (int j = i + 1; j < _split_children.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4116 Interval* i2 = _split_children.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
4117
a61af66fc99e Initial load
duke
parents:
diff changeset
4118 assert(i1->reg_num() != i2->reg_num(), "same register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
4119
a61af66fc99e Initial load
duke
parents:
diff changeset
4120 if (i1->from() < i2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4121 assert(i1->to() <= i2->from() && i1->to() < i2->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4122 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4123 assert(i2->from() < i1->from(), "intervals start at same op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4124 assert(i2->to() <= i1->from() && i2->to() < i1->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4125 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4126 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4130 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4131
a61af66fc99e Initial load
duke
parents:
diff changeset
4132 Interval* Interval::register_hint(bool search_split_child) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4133 if (!search_split_child) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4134 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4136
a61af66fc99e Initial load
duke
parents:
diff changeset
4137 if (_register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4138 assert(_register_hint->is_split_parent(), "ony split parents are valid hint registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
4139
a61af66fc99e Initial load
duke
parents:
diff changeset
4140 if (_register_hint->assigned_reg() >= 0 && _register_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4141 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4142
a61af66fc99e Initial load
duke
parents:
diff changeset
4143 } else if (_register_hint->_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4144 // search the first split child that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4145 int len = _register_hint->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4146 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4147 Interval* cur = _register_hint->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4148
a61af66fc99e Initial load
duke
parents:
diff changeset
4149 if (cur->assigned_reg() >= 0 && cur->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4150 return cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4151 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4155
a61af66fc99e Initial load
duke
parents:
diff changeset
4156 // no hint interval found that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4157 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4159
a61af66fc99e Initial load
duke
parents:
diff changeset
4160
a61af66fc99e Initial load
duke
parents:
diff changeset
4161 Interval* Interval::split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4162 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4163 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4164
a61af66fc99e Initial load
duke
parents:
diff changeset
4165 Interval* result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4166 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4167 result = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4168 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4169 result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4170 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4171
a61af66fc99e Initial load
duke
parents:
diff changeset
4172 // in outputMode, the end of the interval (op_id == cur->to()) is not valid
a61af66fc99e Initial load
duke
parents:
diff changeset
4173 int to_offset = (mode == LIR_OpVisitState::outputMode ? 0 : 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4174
a61af66fc99e Initial load
duke
parents:
diff changeset
4175 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4176 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4177 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4178 if (cur->from() <= op_id && op_id < cur->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4179 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4180 // exchange current split child to start of list (faster access for next call)
a61af66fc99e Initial load
duke
parents:
diff changeset
4181 _split_children.at_put(i, _split_children.at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
4182 _split_children.at_put(0, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4184
a61af66fc99e Initial load
duke
parents:
diff changeset
4185 // interval found
a61af66fc99e Initial load
duke
parents:
diff changeset
4186 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4187 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
4188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4190
a61af66fc99e Initial load
duke
parents:
diff changeset
4191 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4192 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4193 Interval* tmp = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4194 if (tmp != result && tmp->from() <= op_id && op_id < tmp->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4195 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
4196 result->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4197 tmp->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4198 assert(false, "two valid result intervals found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4201 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4203
a61af66fc99e Initial load
duke
parents:
diff changeset
4204 assert(result != NULL, "no matching interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4205 assert(result->covers(op_id, mode), "op_id not covered by interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4206
a61af66fc99e Initial load
duke
parents:
diff changeset
4207 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4208 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4209
a61af66fc99e Initial load
duke
parents:
diff changeset
4210
a61af66fc99e Initial load
duke
parents:
diff changeset
4211 // returns the last split child that ends before the given op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
4212 Interval* Interval::split_child_before_op_id(int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4213 assert(op_id >= 0, "invalid op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4214
a61af66fc99e Initial load
duke
parents:
diff changeset
4215 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4216 Interval* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4217
a61af66fc99e Initial load
duke
parents:
diff changeset
4218 int len = parent->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4219 assert(len > 0, "no split children available");
a61af66fc99e Initial load
duke
parents:
diff changeset
4220
a61af66fc99e Initial load
duke
parents:
diff changeset
4221 for (int i = len - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4222 Interval* cur = parent->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4223 if (cur->to() <= op_id && (result == NULL || result->to() < cur->to())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4224 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4227
a61af66fc99e Initial load
duke
parents:
diff changeset
4228 assert(result != NULL, "no split child found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4229 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4230 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4231
a61af66fc99e Initial load
duke
parents:
diff changeset
4232
a61af66fc99e Initial load
duke
parents:
diff changeset
4233 // checks if op_id is covered by any split child
a61af66fc99e Initial load
duke
parents:
diff changeset
4234 bool Interval::split_child_covers(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4235 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4236 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4237
a61af66fc99e Initial load
duke
parents:
diff changeset
4238 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4239 // simple case if interval was not split
a61af66fc99e Initial load
duke
parents:
diff changeset
4240 return covers(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
4241
a61af66fc99e Initial load
duke
parents:
diff changeset
4242 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4243 // extended case: check all split children
a61af66fc99e Initial load
duke
parents:
diff changeset
4244 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4245 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4246 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4247 if (cur->covers(op_id, mode)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4248 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4251 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4252 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4254
a61af66fc99e Initial load
duke
parents:
diff changeset
4255
a61af66fc99e Initial load
duke
parents:
diff changeset
4256 // Note: use positions are sorted descending -> first use has highest index
a61af66fc99e Initial load
duke
parents:
diff changeset
4257 int Interval::first_usage(IntervalUseKind min_use_kind) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4258 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4259
a61af66fc99e Initial load
duke
parents:
diff changeset
4260 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4261 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4262 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4265 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4266 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4267
a61af66fc99e Initial load
duke
parents:
diff changeset
4268 int Interval::next_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4269 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4270
a61af66fc99e Initial load
duke
parents:
diff changeset
4271 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4272 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
4273 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4275 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4276 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4278
a61af66fc99e Initial load
duke
parents:
diff changeset
4279 int Interval::next_usage_exact(IntervalUseKind exact_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4280 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4281
a61af66fc99e Initial load
duke
parents:
diff changeset
4282 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4283 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
4284 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4286 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4287 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4289
a61af66fc99e Initial load
duke
parents:
diff changeset
4290 int Interval::previous_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4291 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4292
a61af66fc99e Initial load
duke
parents:
diff changeset
4293 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4294 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4295 if (_use_pos_and_kinds.at(i) > from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4296 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4298 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4299 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4300 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4301 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4302 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4303 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4304
a61af66fc99e Initial load
duke
parents:
diff changeset
4305 void Interval::add_use_pos(int pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4306 assert(covers(pos, LIR_OpVisitState::inputMode), "use position not covered by live range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4307
a61af66fc99e Initial load
duke
parents:
diff changeset
4308 // do not add use positions for precolored intervals because
a61af66fc99e Initial load
duke
parents:
diff changeset
4309 // they are never used
a61af66fc99e Initial load
duke
parents:
diff changeset
4310 if (use_kind != noUse && reg_num() >= LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4311 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4312 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4313 for (int i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4314 assert(pos <= _use_pos_and_kinds.at(i), "already added a use-position with lower position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4315 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
4316 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4317 assert(_use_pos_and_kinds.at(i) < _use_pos_and_kinds.at(i - 2), "not sorted descending");
a61af66fc99e Initial load
duke
parents:
diff changeset
4318 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4320 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4321
a61af66fc99e Initial load
duke
parents:
diff changeset
4322 // Note: add_use is called in descending order, so list gets sorted
a61af66fc99e Initial load
duke
parents:
diff changeset
4323 // automatically by just appending new use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4324 int len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4325 if (len == 0 || _use_pos_and_kinds.at(len - 2) > pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4326 _use_pos_and_kinds.append(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4327 _use_pos_and_kinds.append(use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4328 } else if (_use_pos_and_kinds.at(len - 1) < use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4329 assert(_use_pos_and_kinds.at(len - 2) == pos, "list not sorted correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
4330 _use_pos_and_kinds.at_put(len - 1, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4331 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4332 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4334
a61af66fc99e Initial load
duke
parents:
diff changeset
4335 void Interval::add_range(int from, int to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4336 assert(from < to, "invalid range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4337 assert(first() == Range::end() || to < first()->next()->from(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4338 assert(from <= first()->to(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4339
a61af66fc99e Initial load
duke
parents:
diff changeset
4340 if (first()->from() <= to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4341 // join intersecting ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4342 first()->set_from(MIN2(from, first()->from()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4343 first()->set_to (MAX2(to, first()->to()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4344 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4345 // insert new range
a61af66fc99e Initial load
duke
parents:
diff changeset
4346 _first = new Range(from, to, first());
a61af66fc99e Initial load
duke
parents:
diff changeset
4347 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4349
a61af66fc99e Initial load
duke
parents:
diff changeset
4350 Interval* Interval::new_split_child() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4351 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4352 Interval* result = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4353 result->set_type(type());
a61af66fc99e Initial load
duke
parents:
diff changeset
4354
a61af66fc99e Initial load
duke
parents:
diff changeset
4355 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4356 result->_split_parent = parent;
a61af66fc99e Initial load
duke
parents:
diff changeset
4357 result->set_register_hint(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
4358
a61af66fc99e Initial load
duke
parents:
diff changeset
4359 // insert new interval in children-list of parent
a61af66fc99e Initial load
duke
parents:
diff changeset
4360 if (parent->_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4361 assert(is_split_parent(), "list must be initialized at first split");
a61af66fc99e Initial load
duke
parents:
diff changeset
4362
a61af66fc99e Initial load
duke
parents:
diff changeset
4363 parent->_split_children = IntervalList(4);
a61af66fc99e Initial load
duke
parents:
diff changeset
4364 parent->_split_children.append(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4365 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4366 parent->_split_children.append(result);
a61af66fc99e Initial load
duke
parents:
diff changeset
4367
a61af66fc99e Initial load
duke
parents:
diff changeset
4368 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4370
a61af66fc99e Initial load
duke
parents:
diff changeset
4371 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4372 // the remainder as a new interval.
a61af66fc99e Initial load
duke
parents:
diff changeset
4373 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4374 // when an interval is split, a bi-directional link is established between the original interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4375 // (the split parent) and the intervals that are split off this interval (the split children)
a61af66fc99e Initial load
duke
parents:
diff changeset
4376 // When a split child is split again, the new created interval is also a direct child
a61af66fc99e Initial load
duke
parents:
diff changeset
4377 // of the original parent (there is no tree of split children stored, but a flat list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4378 // All split children are spilled to the same stack slot (stored in _canonical_spill_slot)
a61af66fc99e Initial load
duke
parents:
diff changeset
4379 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4380 // Note: The new interval has no valid reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
4381 Interval* Interval::split(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4382 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4383
a61af66fc99e Initial load
duke
parents:
diff changeset
4384 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4385 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4386
a61af66fc99e Initial load
duke
parents:
diff changeset
4387 // split the ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4388 Range* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4389 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4390 while (cur != Range::end() && cur->to() <= split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4391 prev = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4392 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4393 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4394 assert(cur != Range::end(), "split interval after end of last range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4395
a61af66fc99e Initial load
duke
parents:
diff changeset
4396 if (cur->from() < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4397 result->_first = new Range(split_pos, cur->to(), cur->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
4398 cur->set_to(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4399 cur->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4400
a61af66fc99e Initial load
duke
parents:
diff changeset
4401 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4402 assert(prev != NULL, "split before start of first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4403 result->_first = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4404 prev->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4405 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4406 result->_current = result->_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4407 _cached_to = -1; // clear cached value
a61af66fc99e Initial load
duke
parents:
diff changeset
4408
a61af66fc99e Initial load
duke
parents:
diff changeset
4409 // split list of use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4410 int total_len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4411 int start_idx = total_len - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4412 while (start_idx >= 0 && _use_pos_and_kinds.at(start_idx) < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4413 start_idx -= 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4415
a61af66fc99e Initial load
duke
parents:
diff changeset
4416 intStack new_use_pos_and_kinds(total_len - start_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
4417 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4418 for (i = start_idx + 2; i < total_len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4419 new_use_pos_and_kinds.append(_use_pos_and_kinds.at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
4420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4421
a61af66fc99e Initial load
duke
parents:
diff changeset
4422 _use_pos_and_kinds.truncate(start_idx + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4423 result->_use_pos_and_kinds = _use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4424 _use_pos_and_kinds = new_use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4425
a61af66fc99e Initial load
duke
parents:
diff changeset
4426 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4427 assert(_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4428 assert(result->_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4429 assert(_use_pos_and_kinds.length() + result->_use_pos_and_kinds.length() == total_len, "missed some entries");
a61af66fc99e Initial load
duke
parents:
diff changeset
4430
a61af66fc99e Initial load
duke
parents:
diff changeset
4431 for (i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4432 assert(_use_pos_and_kinds.at(i) < split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4433 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
4434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4435 for (i = 0; i < result->_use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4436 assert(result->_use_pos_and_kinds.at(i) >= split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4437 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
4438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4439 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4440
a61af66fc99e Initial load
duke
parents:
diff changeset
4441 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4442 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4443
a61af66fc99e Initial load
duke
parents:
diff changeset
4444 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4445 // the head as a new interval (the original interval is the tail)
a61af66fc99e Initial load
duke
parents:
diff changeset
4446 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4447 // Currently, only the first range can be split, and the new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4448 // must not have split positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4449 Interval* Interval::split_from_start(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4450 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4451 assert(split_pos > from() && split_pos < to(), "can only split inside interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4452 assert(split_pos > _first->from() && split_pos <= _first->to(), "can only split inside first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4453 assert(first_usage(noUse) > split_pos, "can not split when use positions are present");
a61af66fc99e Initial load
duke
parents:
diff changeset
4454
a61af66fc99e Initial load
duke
parents:
diff changeset
4455 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4456 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4457
a61af66fc99e Initial load
duke
parents:
diff changeset
4458 // the new created interval has only one range (checked by assertion above),
a61af66fc99e Initial load
duke
parents:
diff changeset
4459 // so the splitting of the ranges is very simple
a61af66fc99e Initial load
duke
parents:
diff changeset
4460 result->add_range(_first->from(), split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4461
a61af66fc99e Initial load
duke
parents:
diff changeset
4462 if (split_pos == _first->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4463 assert(_first->next() != Range::end(), "must not be at end");
a61af66fc99e Initial load
duke
parents:
diff changeset
4464 _first = _first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4465 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4466 _first->set_from(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4468
a61af66fc99e Initial load
duke
parents:
diff changeset
4469 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4471
a61af66fc99e Initial load
duke
parents:
diff changeset
4472
a61af66fc99e Initial load
duke
parents:
diff changeset
4473 // returns true if the op_id is inside the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4474 bool Interval::covers(int op_id, LIR_OpVisitState::OprMode mode) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4475 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4476
a61af66fc99e Initial load
duke
parents:
diff changeset
4477 while (cur != Range::end() && cur->to() < op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4478 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4480 if (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4481 assert(cur->to() != cur->next()->from(), "ranges not separated");
a61af66fc99e Initial load
duke
parents:
diff changeset
4482
a61af66fc99e Initial load
duke
parents:
diff changeset
4483 if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4484 return cur->from() <= op_id && op_id < cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4485 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4486 return cur->from() <= op_id && op_id <= cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4489 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4491
a61af66fc99e Initial load
duke
parents:
diff changeset
4492 // returns true if the interval has any hole between hole_from and hole_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4493 // (even if the hole has only the length 1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4494 bool Interval::has_hole_between(int hole_from, int hole_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4495 assert(hole_from < hole_to, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4496 assert(from() <= hole_from && hole_to <= to(), "index out of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4497
a61af66fc99e Initial load
duke
parents:
diff changeset
4498 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4499 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4500 assert(cur->to() < cur->next()->from(), "no space between ranges");
a61af66fc99e Initial load
duke
parents:
diff changeset
4501
a61af66fc99e Initial load
duke
parents:
diff changeset
4502 // hole-range starts before this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4503 if (hole_from < cur->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4504 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4505
a61af66fc99e Initial load
duke
parents:
diff changeset
4506 // hole-range completely inside this range -> no hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4507 } else if (hole_to <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4508 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4509
a61af66fc99e Initial load
duke
parents:
diff changeset
4510 // overlapping of hole-range with this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4511 } else if (hole_from <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4512 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4513 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4514
a61af66fc99e Initial load
duke
parents:
diff changeset
4515 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4516 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4517
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
a61af66fc99e Initial load
duke
parents:
diff changeset
4521
a61af66fc99e Initial load
duke
parents:
diff changeset
4522 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4523 void Interval::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4524 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
4525 const char* UseKind2Name[] = { "N", "L", "S", "M" };
a61af66fc99e Initial load
duke
parents:
diff changeset
4526
a61af66fc99e Initial load
duke
parents:
diff changeset
4527 const char* type_name;
a61af66fc99e Initial load
duke
parents:
diff changeset
4528 LIR_Opr opr = LIR_OprFact::illegal();
a61af66fc99e Initial load
duke
parents:
diff changeset
4529 if (reg_num() < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4530 type_name = "fixed";
a61af66fc99e Initial load
duke
parents:
diff changeset
4531 // need a temporary operand for fixed intervals because type() cannot be called
a61af66fc99e Initial load
duke
parents:
diff changeset
4532 if (assigned_reg() >= pd_first_cpu_reg && assigned_reg() <= pd_last_cpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4533 opr = LIR_OprFact::single_cpu(assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4534 } else if (assigned_reg() >= pd_first_fpu_reg && assigned_reg() <= pd_last_fpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4535 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
4536 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4537 } else if (assigned_reg() >= pd_first_xmm_reg && assigned_reg() <= pd_last_xmm_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4538 opr = LIR_OprFact::single_xmm(assigned_reg() - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
4539 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4540 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4541 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
4542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4543 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4544 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
4545 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
4546 (LinearScan::num_physical_regs(type()) == 1 || assigned_regHi() != -1)) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4547 opr = LinearScan::calc_operand_for_interval(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4548 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4549 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4550
a61af66fc99e Initial load
duke
parents:
diff changeset
4551 out->print("%d %s ", reg_num(), type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
4552 if (opr->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4553 out->print("\"");
a61af66fc99e Initial load
duke
parents:
diff changeset
4554 opr->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4555 out->print("\" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
4556 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4557 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
4558
a61af66fc99e Initial load
duke
parents:
diff changeset
4559 // print ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4560 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4561 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4562 cur->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4563 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4564 assert(cur != NULL, "range list not closed with range sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
4565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4566
a61af66fc99e Initial load
duke
parents:
diff changeset
4567 // print use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4568 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4569 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4570 for (int i =_use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4571 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
4572 assert(prev < _use_pos_and_kinds.at(i), "use positions not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
4573
a61af66fc99e Initial load
duke
parents:
diff changeset
4574 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
4575 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4576 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4577
a61af66fc99e Initial load
duke
parents:
diff changeset
4578 out->print(" \"%s\"", SpillState2Name[spill_state()]);
a61af66fc99e Initial load
duke
parents:
diff changeset
4579 out->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4581 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4582
a61af66fc99e Initial load
duke
parents:
diff changeset
4583
a61af66fc99e Initial load
duke
parents:
diff changeset
4584
a61af66fc99e Initial load
duke
parents:
diff changeset
4585 // **** Implementation of IntervalWalker ****************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4586
a61af66fc99e Initial load
duke
parents:
diff changeset
4587 IntervalWalker::IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4588 : _compilation(allocator->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
4589 , _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4590 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4591 _unhandled_first[fixedKind] = unhandled_fixed_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4592 _unhandled_first[anyKind] = unhandled_any_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4593 _active_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4594 _inactive_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4595 _active_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4596 _inactive_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4597 _current_position = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4598 _current = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4599 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4601
a61af66fc99e Initial load
duke
parents:
diff changeset
4602
a61af66fc99e Initial load
duke
parents:
diff changeset
4603 // append interval at top of list
a61af66fc99e Initial load
duke
parents:
diff changeset
4604 void IntervalWalker::append_unsorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4605 interval->set_next(*list); *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4606 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4607
a61af66fc99e Initial load
duke
parents:
diff changeset
4608
a61af66fc99e Initial load
duke
parents:
diff changeset
4609 // append interval in order of current range from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4610 void IntervalWalker::append_sorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4611 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4612 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4613 while (cur->current_from() < interval->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4614 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4615 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4616 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4617 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4618 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4619 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4621 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4623
a61af66fc99e Initial load
duke
parents:
diff changeset
4624 void IntervalWalker::append_to_unhandled(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4625 assert(interval->from() >= current()->current_from(), "cannot append new interval before current walk position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4626
a61af66fc99e Initial load
duke
parents:
diff changeset
4627 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4628 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4629 while (cur->from() < interval->from() || (cur->from() == interval->from() && cur->first_usage(noUse) < interval->first_usage(noUse))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4630 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4632 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4633 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4634 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4635 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4636 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4637 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4638 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4639
a61af66fc99e Initial load
duke
parents:
diff changeset
4640
a61af66fc99e Initial load
duke
parents:
diff changeset
4641 inline bool IntervalWalker::remove_from_list(Interval** list, Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4642 while (*list != Interval::end() && *list != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4643 list = (*list)->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4644 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4645 if (*list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4646 assert(*list == i, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4647 *list = (*list)->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4648 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4649 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4650 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4653
a61af66fc99e Initial load
duke
parents:
diff changeset
4654 void IntervalWalker::remove_from_list(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4655 bool deleted;
a61af66fc99e Initial load
duke
parents:
diff changeset
4656
a61af66fc99e Initial load
duke
parents:
diff changeset
4657 if (i->state() == activeState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4658 deleted = remove_from_list(active_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4659 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4660 assert(i->state() == inactiveState, "invalid state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4661 deleted = remove_from_list(inactive_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4662 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4663
a61af66fc99e Initial load
duke
parents:
diff changeset
4664 assert(deleted, "interval has not been found in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
4665 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4666
a61af66fc99e Initial load
duke
parents:
diff changeset
4667
a61af66fc99e Initial load
duke
parents:
diff changeset
4668 void IntervalWalker::walk_to(IntervalState state, int from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4669 assert (state == activeState || state == inactiveState, "wrong state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4670 for_each_interval_kind(kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4671 Interval** prev = state == activeState ? active_first_addr(kind) : inactive_first_addr(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4672 Interval* next = *prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4673 while (next->current_from() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4674 Interval* cur = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4675 next = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4676
a61af66fc99e Initial load
duke
parents:
diff changeset
4677 bool range_has_changed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4678 while (cur->current_to() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4679 cur->next_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4680 range_has_changed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4681 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4682
a61af66fc99e Initial load
duke
parents:
diff changeset
4683 // also handle move from inactive list to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4684 range_has_changed = range_has_changed || (state == inactiveState && cur->current_from() <= from);
a61af66fc99e Initial load
duke
parents:
diff changeset
4685
a61af66fc99e Initial load
duke
parents:
diff changeset
4686 if (range_has_changed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4687 // remove cur from list
a61af66fc99e Initial load
duke
parents:
diff changeset
4688 *prev = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4689 if (cur->current_at_end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4690 // move to handled state (not maintained as a list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4691 cur->set_state(handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4692 interval_moved(cur, kind, state, handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4693 } else if (cur->current_from() <= from){
a61af66fc99e Initial load
duke
parents:
diff changeset
4694 // sort into active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4695 append_sorted(active_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4696 cur->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4697 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4698 assert(state == activeState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4699 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4700 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4701 interval_moved(cur, kind, state, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4702 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4703 // sort into inactive list
a61af66fc99e Initial load
duke
parents:
diff changeset
4704 append_sorted(inactive_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4705 cur->set_state(inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4706 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4707 assert(state == inactiveState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4708 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4710 interval_moved(cur, kind, state, inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4711 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4712 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4713 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4714 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
4715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4716 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4718 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4719
a61af66fc99e Initial load
duke
parents:
diff changeset
4720
a61af66fc99e Initial load
duke
parents:
diff changeset
4721 void IntervalWalker::next_interval() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4722 IntervalKind kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4723 Interval* any = _unhandled_first[anyKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4724 Interval* fixed = _unhandled_first[fixedKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4725
a61af66fc99e Initial load
duke
parents:
diff changeset
4726 if (any != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4727 // intervals may start at same position -> prefer fixed interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4728 kind = fixed != Interval::end() && fixed->from() <= any->from() ? fixedKind : anyKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4729
a61af66fc99e Initial load
duke
parents:
diff changeset
4730 assert (kind == fixedKind && fixed->from() <= any->from() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
4731 kind == anyKind && any->from() <= fixed->from(), "wrong interval!!!");
a61af66fc99e Initial load
duke
parents:
diff changeset
4732 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
4733
a61af66fc99e Initial load
duke
parents:
diff changeset
4734 } else if (fixed != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4735 kind = fixedKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4736 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4737 _current = NULL; return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4738 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4739 _current_kind = kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4740 _current = _unhandled_first[kind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4741 _unhandled_first[kind] = _current->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4742 _current->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4743 _current->rewind_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4744 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4745
a61af66fc99e Initial load
duke
parents:
diff changeset
4746
a61af66fc99e Initial load
duke
parents:
diff changeset
4747 void IntervalWalker::walk_to(int lir_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4748 assert(_current_position <= lir_op_id, "can not walk backwards");
a61af66fc99e Initial load
duke
parents:
diff changeset
4749 while (current() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4750 bool is_active = current()->from() <= lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4751 int id = is_active ? current()->from() : lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4752
a61af66fc99e Initial load
duke
parents:
diff changeset
4753 TRACE_LINEAR_SCAN(2, if (_current_position < id) { tty->cr(); tty->print_cr("walk_to(%d) **************************************************************", id); })
a61af66fc99e Initial load
duke
parents:
diff changeset
4754
a61af66fc99e Initial load
duke
parents:
diff changeset
4755 // set _current_position prior to call of walk_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4756 _current_position = id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4757
a61af66fc99e Initial load
duke
parents:
diff changeset
4758 // call walk_to even if _current_position == id
a61af66fc99e Initial load
duke
parents:
diff changeset
4759 walk_to(activeState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4760 walk_to(inactiveState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4761
a61af66fc99e Initial load
duke
parents:
diff changeset
4762 if (is_active) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4763 current()->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4764 if (activate_current()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4765 append_sorted(active_first_addr(current_kind()), current());
a61af66fc99e Initial load
duke
parents:
diff changeset
4766 interval_moved(current(), current_kind(), unhandledState, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4767 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4768
a61af66fc99e Initial load
duke
parents:
diff changeset
4769 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4770 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4771 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4772 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4773 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4774 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4775
a61af66fc99e Initial load
duke
parents:
diff changeset
4776 void IntervalWalker::interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4777 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4778 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4779 #define print_state(state) \
a61af66fc99e Initial load
duke
parents:
diff changeset
4780 switch(state) {\
a61af66fc99e Initial load
duke
parents:
diff changeset
4781 case unhandledState: tty->print("unhandled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4782 case activeState: tty->print("active"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4783 case inactiveState: tty->print("inactive"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4784 case handledState: tty->print("handled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4785 default: ShouldNotReachHere(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
4786 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4787
a61af66fc99e Initial load
duke
parents:
diff changeset
4788 print_state(from); tty->print(" to "); print_state(to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4789 tty->fill_to(23);
a61af66fc99e Initial load
duke
parents:
diff changeset
4790 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4791
a61af66fc99e Initial load
duke
parents:
diff changeset
4792 #undef print_state
a61af66fc99e Initial load
duke
parents:
diff changeset
4793 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4794 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4795 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4796
a61af66fc99e Initial load
duke
parents:
diff changeset
4797
a61af66fc99e Initial load
duke
parents:
diff changeset
4798
a61af66fc99e Initial load
duke
parents:
diff changeset
4799 // **** Implementation of LinearScanWalker **************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4800
a61af66fc99e Initial load
duke
parents:
diff changeset
4801 LinearScanWalker::LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4802 : IntervalWalker(allocator, unhandled_fixed_first, unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4803 , _move_resolver(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4804 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4805 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4806 _spill_intervals[i] = new IntervalList(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4807 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4808 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4809
a61af66fc99e Initial load
duke
parents:
diff changeset
4810
a61af66fc99e Initial load
duke
parents:
diff changeset
4811 inline void LinearScanWalker::init_use_lists(bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4812 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4813 _use_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4814
a61af66fc99e Initial load
duke
parents:
diff changeset
4815 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4816 _block_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4817 _spill_intervals[i]->clear();
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
a61af66fc99e Initial load
duke
parents:
diff changeset
4822 inline void LinearScanWalker::exclude_from_use(int reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4823 assert(reg < LinearScan::nof_regs, "interval must have a register assigned (stack slots not allowed)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4824 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4825 _use_pos[reg] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4826 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4828 inline void LinearScanWalker::exclude_from_use(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4829 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4830
a61af66fc99e Initial load
duke
parents:
diff changeset
4831 exclude_from_use(i->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4832 exclude_from_use(i->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
4833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4834
a61af66fc99e Initial load
duke
parents:
diff changeset
4835 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
4836 assert(use_pos != 0, "must use exclude_from_use to set use_pos to 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
4837
a61af66fc99e Initial load
duke
parents:
diff changeset
4838 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4839 if (_use_pos[reg] > use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4840 _use_pos[reg] = use_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4842 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4843 _spill_intervals[reg]->append(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4844 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4845 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4846 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4847 inline void LinearScanWalker::set_use_pos(Interval* i, int use_pos, bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4848 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4849 if (use_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4850 set_use_pos(i->assigned_reg(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4851 set_use_pos(i->assigned_regHi(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4852 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4853 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4854
a61af66fc99e Initial load
duke
parents:
diff changeset
4855 inline void LinearScanWalker::set_block_pos(int reg, Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4856 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4857 if (_block_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4858 _block_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4860 if (_use_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4861 _use_pos[reg] = block_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(Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4866 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4867 if (block_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4868 set_block_pos(i->assigned_reg(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4869 set_block_pos(i->assigned_regHi(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4870 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4871 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4872
a61af66fc99e Initial load
duke
parents:
diff changeset
4873
a61af66fc99e Initial load
duke
parents:
diff changeset
4874 void LinearScanWalker::free_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4875 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4876 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4877 assert(list->assigned_reg() < LinearScan::nof_regs, "active interval must have a register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4878 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4879 list = list->next();
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 void LinearScanWalker::free_exclude_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4884 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4885 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4886 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4887 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4888 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4889 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4890
a61af66fc99e Initial load
duke
parents:
diff changeset
4891 void LinearScanWalker::free_collect_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4892 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4893 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4894 if (cur->to() <= list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4895 assert(list->current_intersects_at(cur) == -1, "must not intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4896 set_use_pos(list, list->current_from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4897 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4898 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4899 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4900 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4901 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4903
a61af66fc99e Initial load
duke
parents:
diff changeset
4904 void LinearScanWalker::free_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4905 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4906 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4907 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4908 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4910 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4911
a61af66fc99e Initial load
duke
parents:
diff changeset
4912 void LinearScanWalker::free_collect_unhandled(IntervalKind kind, Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4913 Interval* list = unhandled_first(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4914 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4915 set_use_pos(list, list->intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4916 if (kind == fixedKind && cur->to() <= list->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4917 set_use_pos(list, list->from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4918 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4919 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4920 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4921 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4922
a61af66fc99e Initial load
duke
parents:
diff changeset
4923 void LinearScanWalker::spill_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4924 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4925 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4926 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4927 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4928 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4929 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4930
a61af66fc99e Initial load
duke
parents:
diff changeset
4931 void LinearScanWalker::spill_block_unhandled_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4932 Interval* list = unhandled_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4933 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4934 set_block_pos(list, list->intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4935 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4938
a61af66fc99e Initial load
duke
parents:
diff changeset
4939 void LinearScanWalker::spill_block_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4940 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4941 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4942 if (cur->to() > list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4943 set_block_pos(list, list->current_intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4944 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4945 assert(list->current_intersects_at(cur) == -1, "invalid optimization: intervals intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4946 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4947
a61af66fc99e Initial load
duke
parents:
diff changeset
4948 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4949 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4950 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4951
a61af66fc99e Initial load
duke
parents:
diff changeset
4952 void LinearScanWalker::spill_collect_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4953 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4954 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4955 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4956 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4958 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4959
a61af66fc99e Initial load
duke
parents:
diff changeset
4960 void LinearScanWalker::spill_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4961 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4962 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4963 if (list->current_intersects(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4964 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4965 }
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
a61af66fc99e Initial load
duke
parents:
diff changeset
4971 void LinearScanWalker::insert_move(int op_id, Interval* src_it, Interval* dst_it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4972 // output all moves here. When source and target are equal, the move is
a61af66fc99e Initial load
duke
parents:
diff changeset
4973 // optimized away later in assign_reg_nums
a61af66fc99e Initial load
duke
parents:
diff changeset
4974
a61af66fc99e Initial load
duke
parents:
diff changeset
4975 op_id = (op_id + 1) & ~1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4976 BlockBegin* op_block = allocator()->block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4977 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
4978
a61af66fc99e Initial load
duke
parents:
diff changeset
4979 // calculate index of instruction inside instruction list of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
4980 // the minimal index (for a block with no spill moves) can be calculated because the
a61af66fc99e Initial load
duke
parents:
diff changeset
4981 // numbering of instructions is known.
a61af66fc99e Initial load
duke
parents:
diff changeset
4982 // When the block already contains spill moves, the index must be increased until the
a61af66fc99e Initial load
duke
parents:
diff changeset
4983 // correct index is reached.
a61af66fc99e Initial load
duke
parents:
diff changeset
4984 LIR_OpList* list = op_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
4985 int index = (op_id - list->at(0)->id()) / 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4986 assert(list->at(index)->id() <= op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4987
a61af66fc99e Initial load
duke
parents:
diff changeset
4988 while (list->at(index)->id() != op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4989 index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
4990 assert(0 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
4991 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4992 assert(1 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
4993 assert(list->at(index)->id() == op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4994
a61af66fc99e Initial load
duke
parents:
diff changeset
4995 // insert new instruction before instruction at position index
a61af66fc99e Initial load
duke
parents:
diff changeset
4996 _move_resolver.move_insert_position(op_block->lir(), index - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4997 _move_resolver.add_mapping(src_it, dst_it);
a61af66fc99e Initial load
duke
parents:
diff changeset
4998 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4999
a61af66fc99e Initial load
duke
parents:
diff changeset
5000
a61af66fc99e Initial load
duke
parents:
diff changeset
5001 int LinearScanWalker::find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5002 int from_block_nr = min_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5003 int to_block_nr = max_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5004
a61af66fc99e Initial load
duke
parents:
diff changeset
5005 assert(0 <= from_block_nr && from_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5006 assert(0 <= to_block_nr && to_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5007 assert(from_block_nr < to_block_nr, "must cross block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
5008
a61af66fc99e Initial load
duke
parents:
diff changeset
5009 // Try to split at end of max_block. If this would be after
a61af66fc99e Initial load
duke
parents:
diff changeset
5010 // max_split_pos, then use the begin of max_block
a61af66fc99e Initial load
duke
parents:
diff changeset
5011 int optimal_split_pos = max_block->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5012 if (optimal_split_pos > max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5013 optimal_split_pos = max_block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
5014 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5015
a61af66fc99e Initial load
duke
parents:
diff changeset
5016 int min_loop_depth = max_block->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
5017 for (int i = to_block_nr - 1; i >= from_block_nr; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5018 BlockBegin* cur = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5019
a61af66fc99e Initial load
duke
parents:
diff changeset
5020 if (cur->loop_depth() < min_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5021 // block with lower loop-depth found -> split at the end of this block
a61af66fc99e Initial load
duke
parents:
diff changeset
5022 min_loop_depth = cur->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
5023 optimal_split_pos = cur->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5024 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5025 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5026 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
5027
a61af66fc99e Initial load
duke
parents:
diff changeset
5028 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5030
a61af66fc99e Initial load
duke
parents:
diff changeset
5031
a61af66fc99e Initial load
duke
parents:
diff changeset
5032 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
5033 int optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5034 if (min_split_pos == max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5035 // trivial case, no optimization of split position possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5036 TRACE_LINEAR_SCAN(4, tty->print_cr(" min-pos and max-pos are equal, no optimization possible"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5037 optimal_split_pos = min_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5038
a61af66fc99e Initial load
duke
parents:
diff changeset
5039 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5040 assert(min_split_pos < max_split_pos, "must be true then");
a61af66fc99e Initial load
duke
parents:
diff changeset
5041 assert(min_split_pos > 0, "cannot access min_split_pos - 1 otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5042
a61af66fc99e Initial load
duke
parents:
diff changeset
5043 // reason for using min_split_pos - 1: when the minimal split pos is exactly at the
a61af66fc99e Initial load
duke
parents:
diff changeset
5044 // beginning of a block, then min_split_pos is also a possible split position.
a61af66fc99e Initial load
duke
parents:
diff changeset
5045 // 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
5046 BlockBegin* min_block = allocator()->block_of_op_with_id(min_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5047
a61af66fc99e Initial load
duke
parents:
diff changeset
5048 // reason for using max_split_pos - 1: otherwise there would be an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
5049 // when an interval ends at the end of the last block of the method
a61af66fc99e Initial load
duke
parents:
diff changeset
5050 // (in this case, max_split_pos == allocator()->max_lir_op_id() + 2, and there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
5051 // block at this op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5052 BlockBegin* max_block = allocator()->block_of_op_with_id(max_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5053
a61af66fc99e Initial load
duke
parents:
diff changeset
5054 assert(min_block->linear_scan_number() <= max_block->linear_scan_number(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5055 if (min_block == max_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5056 // split position cannot be moved to block boundary, so split as late as possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5057 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
5058 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5059
a61af66fc99e Initial load
duke
parents:
diff changeset
5060 } 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
5061 // Do not move split position if the interval has a hole before max_split_pos.
a61af66fc99e Initial load
duke
parents:
diff changeset
5062 // Intervals resulting from Phi-Functions have more than one definition (marked
a61af66fc99e Initial load
duke
parents:
diff changeset
5063 // as mustHaveRegister) with a hole before each definition. When the register is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5064 // for the second definition, an earlier reloading is unnecessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
5065 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
5066 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5067
a61af66fc99e Initial load
duke
parents:
diff changeset
5068 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5069 // seach optimal block boundary between min_split_pos and max_split_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5070 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
5071
a61af66fc99e Initial load
duke
parents:
diff changeset
5072 if (do_loop_optimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5073 // Loop optimization: if a loop-end marker is found between min- and max-position,
a61af66fc99e Initial load
duke
parents:
diff changeset
5074 // then split before this loop
a61af66fc99e Initial load
duke
parents:
diff changeset
5075 int loop_end_pos = it->next_usage_exact(loopEndMarker, min_block->last_lir_instruction_id() + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5076 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
5077
a61af66fc99e Initial load
duke
parents:
diff changeset
5078 assert(loop_end_pos > min_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5079 if (loop_end_pos < max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5080 // loop-end marker found between min- and max-position
a61af66fc99e Initial load
duke
parents:
diff changeset
5081 // if it is not the end marker for the same loop as the min-position, then move
a61af66fc99e Initial load
duke
parents:
diff changeset
5082 // the max-position to this loop block.
a61af66fc99e Initial load
duke
parents:
diff changeset
5083 // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5084 // of the interval (normally, only mustHaveRegister causes a reloading)
a61af66fc99e Initial load
duke
parents:
diff changeset
5085 BlockBegin* loop_block = allocator()->block_of_op_with_id(loop_end_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5086
a61af66fc99e Initial load
duke
parents:
diff changeset
5087 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
5088 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
5089
a61af66fc99e Initial load
duke
parents:
diff changeset
5090 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
5091 if (optimal_split_pos == loop_block->last_lir_instruction_id() + 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5092 optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5093 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization not necessary"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5094 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5095 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization successful"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5096 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5097 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5098 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5099
a61af66fc99e Initial load
duke
parents:
diff changeset
5100 if (optimal_split_pos == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5101 // not calculated by loop optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5102 optimal_split_pos = find_optimal_split_pos(min_block, max_block, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5103 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5106 TRACE_LINEAR_SCAN(4, tty->print_cr(" optimal split position: %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5107
a61af66fc99e Initial load
duke
parents:
diff changeset
5108 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5109 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5110
a61af66fc99e Initial load
duke
parents:
diff changeset
5111
a61af66fc99e Initial load
duke
parents:
diff changeset
5112 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5113 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5114 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5115 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5116 2) the right part is sorted into to the unhandled-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5117 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5118 void LinearScanWalker::split_before_usage(Interval* it, int min_split_pos, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5119 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5120 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5121
a61af66fc99e Initial load
duke
parents:
diff changeset
5122 assert(it->from() < min_split_pos, "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5123 assert(current_position() < min_split_pos, "cannot split before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5124 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5125 assert(max_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5126
a61af66fc99e Initial load
duke
parents:
diff changeset
5127 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5128
a61af66fc99e Initial load
duke
parents:
diff changeset
5129 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5130 assert(optimal_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5131 assert(optimal_split_pos > it->from(), "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5132
a61af66fc99e Initial load
duke
parents:
diff changeset
5133 if (optimal_split_pos == it->to() && it->next_usage(mustHaveRegister, min_split_pos) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5134 // the split position would be just before the end of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5135 // -> no split at all necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5136 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
5137 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5139
a61af66fc99e Initial load
duke
parents:
diff changeset
5140 // 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
5141 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
5142
a61af66fc99e Initial load
duke
parents:
diff changeset
5143 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5144 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5145 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5147
a61af66fc99e Initial load
duke
parents:
diff changeset
5148 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5149 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
5150 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
5151
a61af66fc99e Initial load
duke
parents:
diff changeset
5152 Interval* split_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5153
a61af66fc99e Initial load
duke
parents:
diff changeset
5154 allocator()->append_interval(split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5155 allocator()->copy_register_flags(it, split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5156 split_part->set_insert_move_when_activated(move_necessary);
a61af66fc99e Initial load
duke
parents:
diff changeset
5157 append_to_unhandled(unhandled_first_addr(anyKind), split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5158
a61af66fc99e Initial load
duke
parents:
diff changeset
5159 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
5160 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5161 TRACE_LINEAR_SCAN(2, tty->print (" "); split_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5162 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5163
a61af66fc99e Initial load
duke
parents:
diff changeset
5164 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5165 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5166 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5167 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5168 2) the right part is always on the stack and therefore ignored in further processing
a61af66fc99e Initial load
duke
parents:
diff changeset
5169 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5170 void LinearScanWalker::split_for_spilling(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5171 // calculate allowed range of splitting position
a61af66fc99e Initial load
duke
parents:
diff changeset
5172 int max_split_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5173 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, max_split_pos) + 1, it->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5174
a61af66fc99e Initial load
duke
parents:
diff changeset
5175 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting and spilling interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5176 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5177
a61af66fc99e Initial load
duke
parents:
diff changeset
5178 assert(it->state() == activeState, "why spill interval that is not active?");
a61af66fc99e Initial load
duke
parents:
diff changeset
5179 assert(it->from() <= min_split_pos, "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5180 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5181 assert(max_split_pos < it->to(), "cannot split at end end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5182 assert(current_position() < it->to(), "interval must not end before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5183
a61af66fc99e Initial load
duke
parents:
diff changeset
5184 if (min_split_pos == it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5185 // the whole interval is never used, so spill it entirely to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
5186 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
5187 assert(it->first_usage(shouldHaveRegister) > current_position(), "interval must not have use position before current_position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5188
a61af66fc99e Initial load
duke
parents:
diff changeset
5189 allocator()->assign_spill_slot(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5190 allocator()->change_spill_state(it, min_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5191
a61af66fc99e Initial load
duke
parents:
diff changeset
5192 // Also kick parent intervals out of register to memory when they have no use
a61af66fc99e Initial load
duke
parents:
diff changeset
5193 // position. This avoids short interval in register surrounded by intervals in
a61af66fc99e Initial load
duke
parents:
diff changeset
5194 // memory -> avoid useless moves from memory to register and back
a61af66fc99e Initial load
duke
parents:
diff changeset
5195 Interval* parent = it;
a61af66fc99e Initial load
duke
parents:
diff changeset
5196 while (parent != NULL && parent->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5197 parent = parent->split_child_before_op_id(parent->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5198
a61af66fc99e Initial load
duke
parents:
diff changeset
5199 if (parent->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5200 if (parent->first_usage(shouldHaveRegister) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5201 // parent is never used, so kick it out of its assigned register
a61af66fc99e Initial load
duke
parents:
diff changeset
5202 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
5203 allocator()->assign_spill_slot(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
5204 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5205 // do not go further back because the register is actually used by the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5206 parent = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5207 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5208 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5210
a61af66fc99e Initial load
duke
parents:
diff changeset
5211 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5212 // search optimal split pos, split interval and spill only the right hand part
a61af66fc99e Initial load
duke
parents:
diff changeset
5213 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5214
a61af66fc99e Initial load
duke
parents:
diff changeset
5215 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5216 assert(optimal_split_pos < it->to(), "cannot split at end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5217 assert(optimal_split_pos >= it->from(), "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5218
a61af66fc99e Initial load
duke
parents:
diff changeset
5219 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5220 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5221 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5223
a61af66fc99e Initial load
duke
parents:
diff changeset
5224 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5225 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
5226 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
5227
a61af66fc99e Initial load
duke
parents:
diff changeset
5228 Interval* spilled_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5229 allocator()->append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5230 allocator()->assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5231 allocator()->change_spill_state(spilled_part, optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5232
a61af66fc99e Initial load
duke
parents:
diff changeset
5233 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5234 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
5235 insert_move(optimal_split_pos, it, spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5237
a61af66fc99e Initial load
duke
parents:
diff changeset
5238 // the current_split_child is needed later when moves are inserted for reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5239 assert(spilled_part->current_split_child() == it, "overwriting wrong current_split_child");
a61af66fc99e Initial load
duke
parents:
diff changeset
5240 spilled_part->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5241
a61af66fc99e Initial load
duke
parents:
diff changeset
5242 TRACE_LINEAR_SCAN(2, tty->print_cr(" split interval in two parts"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5243 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5244 TRACE_LINEAR_SCAN(2, tty->print (" "); spilled_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5245 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5246 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5247
a61af66fc99e Initial load
duke
parents:
diff changeset
5248
a61af66fc99e Initial load
duke
parents:
diff changeset
5249 void LinearScanWalker::split_stack_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5250 int min_split_pos = current_position() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5251 int max_split_pos = MIN2(it->first_usage(shouldHaveRegister), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5252
a61af66fc99e Initial load
duke
parents:
diff changeset
5253 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5255
a61af66fc99e Initial load
duke
parents:
diff changeset
5256 void LinearScanWalker::split_when_partial_register_available(Interval* it, int register_available_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5257 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, register_available_until), it->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5258 int max_split_pos = register_available_until;
a61af66fc99e Initial load
duke
parents:
diff changeset
5259
a61af66fc99e Initial load
duke
parents:
diff changeset
5260 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5262
a61af66fc99e Initial load
duke
parents:
diff changeset
5263 void LinearScanWalker::split_and_spill_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5264 assert(it->state() == activeState || it->state() == inactiveState, "other states not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5265
a61af66fc99e Initial load
duke
parents:
diff changeset
5266 int current_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5267 if (it->state() == inactiveState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5268 // the interval is currently inactive, so no spill slot is needed for now.
a61af66fc99e Initial load
duke
parents:
diff changeset
5269 // when the split part is activated, the interval has a new chance to get a register,
a61af66fc99e Initial load
duke
parents:
diff changeset
5270 // so in the best case no stack slot is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5271 assert(it->has_hole_between(current_pos - 1, current_pos + 1), "interval can not be inactive otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5272 split_before_usage(it, current_pos + 1, current_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5273
a61af66fc99e Initial load
duke
parents:
diff changeset
5274 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5275 // search the position where the interval must have a register and split
a61af66fc99e Initial load
duke
parents:
diff changeset
5276 // at the optimal position before.
a61af66fc99e Initial load
duke
parents:
diff changeset
5277 // The new created part is added to the unhandled list and will get a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5278 // when it is activated
a61af66fc99e Initial load
duke
parents:
diff changeset
5279 int min_split_pos = current_pos + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5280 int max_split_pos = MIN2(it->next_usage(mustHaveRegister, min_split_pos), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5281
a61af66fc99e Initial load
duke
parents:
diff changeset
5282 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5283
a61af66fc99e Initial load
duke
parents:
diff changeset
5284 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
5285 split_for_spilling(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5286 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5288
a61af66fc99e Initial load
duke
parents:
diff changeset
5289
a61af66fc99e Initial load
duke
parents:
diff changeset
5290 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
5291 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5292 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5293
a61af66fc99e Initial load
duke
parents:
diff changeset
5294 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5295 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5296 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5297
a61af66fc99e Initial load
duke
parents:
diff changeset
5298 } else if (_use_pos[i] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5299 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5300 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
5301 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5302 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5303 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5304 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5305 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
5306 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5310
a61af66fc99e Initial load
duke
parents:
diff changeset
5311 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5312 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5313 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5314 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5315 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5316 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5317 return any_reg;
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 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
5322 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5323
a61af66fc99e Initial load
duke
parents:
diff changeset
5324 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5325 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5326
a61af66fc99e Initial load
duke
parents:
diff changeset
5327 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5328 if (_use_pos[i] >= interval_to && _use_pos[i + 1] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5329 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5330 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
5331 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5332 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5333 } else if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5334 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5335 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
5336 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5338 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5339 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5340
a61af66fc99e Initial load
duke
parents:
diff changeset
5341 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5342 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5343 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5344 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5345 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5346 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5347 return any_reg;
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
a61af66fc99e Initial load
duke
parents:
diff changeset
5352 bool LinearScanWalker::alloc_free_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5353 TRACE_LINEAR_SCAN(2, tty->print("trying to find free register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5354
a61af66fc99e Initial load
duke
parents:
diff changeset
5355 init_use_lists(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5356 free_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5357 free_exclude_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5358 free_collect_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5359 free_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5360 // free_collect_unhandled(fixedKind, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5361 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
5362
a61af66fc99e Initial load
duke
parents:
diff changeset
5363 // _use_pos contains the start of the next interval that has this register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5364 // (either as a fixed register or a normal allocated register in the past)
a61af66fc99e Initial load
duke
parents:
diff changeset
5365 // only intervals overlapping with cur are processed, non-overlapping invervals can be ignored safely
a61af66fc99e Initial load
duke
parents:
diff changeset
5366 TRACE_LINEAR_SCAN(4, tty->print_cr(" state of registers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5367 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
5368
a61af66fc99e Initial load
duke
parents:
diff changeset
5369 int hint_reg, hint_regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5370 Interval* register_hint = cur->register_hint();
a61af66fc99e Initial load
duke
parents:
diff changeset
5371 if (register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5372 hint_reg = register_hint->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5373 hint_regHi = register_hint->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
5374
a61af66fc99e Initial load
duke
parents:
diff changeset
5375 if (allocator()->is_precolored_cpu_interval(register_hint)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5376 assert(hint_reg != any_reg && hint_regHi == any_reg, "must be for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
5377 hint_regHi = hint_reg + 1; // connect e.g. eax-edx
a61af66fc99e Initial load
duke
parents:
diff changeset
5378 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5379 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
5380
a61af66fc99e Initial load
duke
parents:
diff changeset
5381 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5382 hint_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5383 hint_regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5385 assert(hint_reg == any_reg || hint_reg != hint_regHi, "hint reg and regHi equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
5386 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned to interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5387
a61af66fc99e Initial load
duke
parents:
diff changeset
5388 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5389 int reg_needed_until = cur->from() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5390 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5391
a61af66fc99e Initial load
duke
parents:
diff changeset
5392 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5393 int split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5394 int reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5395 int regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5396
a61af66fc99e Initial load
duke
parents:
diff changeset
5397 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5398 reg = find_free_double_reg(reg_needed_until, interval_to, hint_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5399 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5400 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5401 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5402 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5403 split_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5404
a61af66fc99e Initial load
duke
parents:
diff changeset
5405 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5406 reg = find_free_reg(reg_needed_until, interval_to, hint_reg, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5407 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5408 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5409 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5410 split_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5411
a61af66fc99e Initial load
duke
parents:
diff changeset
5412 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5413 regHi = find_free_reg(reg_needed_until, interval_to, hint_regHi, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5414
a61af66fc99e Initial load
duke
parents:
diff changeset
5415 if (_use_pos[reg] < interval_to && regHi == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5416 // do not split interval if only one register can be assigned until the split pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5417 // (when one register is found for the whole interval, split&spill is only
a61af66fc99e Initial load
duke
parents:
diff changeset
5418 // performed for the hi register)
a61af66fc99e Initial load
duke
parents:
diff changeset
5419 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5420
a61af66fc99e Initial load
duke
parents:
diff changeset
5421 } else if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5422 split_pos = MIN2(split_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5423
a61af66fc99e Initial load
duke
parents:
diff changeset
5424 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5425 if (reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5426 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5427 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5428 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5431 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5433
a61af66fc99e Initial load
duke
parents:
diff changeset
5434 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5435 TRACE_LINEAR_SCAN(2, tty->print_cr("selected register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5436
a61af66fc99e Initial load
duke
parents:
diff changeset
5437 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5438 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5439 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5440 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5441 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5442
a61af66fc99e Initial load
duke
parents:
diff changeset
5443 // only return true if interval is completely assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5444 return _num_phys_regs == 1 || regHi != any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5446
a61af66fc99e Initial load
duke
parents:
diff changeset
5447
a61af66fc99e Initial load
duke
parents:
diff changeset
5448 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
5449 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5450
a61af66fc99e Initial load
duke
parents:
diff changeset
5451 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5452 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5453 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5454
a61af66fc99e Initial load
duke
parents:
diff changeset
5455 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5456 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
5457 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5458 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5461
a61af66fc99e Initial load
duke
parents:
diff changeset
5462 if (max_reg != any_reg && _block_pos[max_reg] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5463 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5464 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5465
a61af66fc99e Initial load
duke
parents:
diff changeset
5466 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5468
a61af66fc99e Initial load
duke
parents:
diff changeset
5469 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
5470 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5471
a61af66fc99e Initial load
duke
parents:
diff changeset
5472 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5473
a61af66fc99e Initial load
duke
parents:
diff changeset
5474 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5475 if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5476 if (max_reg == any_reg || _use_pos[i] > _use_pos[max_reg]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5477 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5478 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5479 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5481
a61af66fc99e Initial load
duke
parents:
diff changeset
5482 if (_block_pos[max_reg] <= interval_to || _block_pos[max_reg + 1] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5483 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5484 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5485
a61af66fc99e Initial load
duke
parents:
diff changeset
5486 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5488
a61af66fc99e Initial load
duke
parents:
diff changeset
5489 void LinearScanWalker::split_and_spill_intersecting_intervals(int reg, int regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5490 assert(reg != any_reg, "no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5491
a61af66fc99e Initial load
duke
parents:
diff changeset
5492 for (int i = 0; i < _spill_intervals[reg]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5493 Interval* it = _spill_intervals[reg]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5494 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5495 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5496 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5497
a61af66fc99e Initial load
duke
parents:
diff changeset
5498 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5499 IntervalList* processed = _spill_intervals[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5500 for (int i = 0; i < _spill_intervals[regHi]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5501 Interval* it = _spill_intervals[regHi]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5502 if (processed->index_of(it) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5503 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5504 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5505 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5506 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5507 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5508 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5509
a61af66fc99e Initial load
duke
parents:
diff changeset
5510
a61af66fc99e Initial load
duke
parents:
diff changeset
5511 // Split an Interval and spill it to memory so that cur can be placed in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5512 void LinearScanWalker::alloc_locked_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5513 TRACE_LINEAR_SCAN(2, tty->print("need to split and spill to get register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5514
a61af66fc99e Initial load
duke
parents:
diff changeset
5515 // collect current usage of registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5516 init_use_lists(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5517 spill_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5518 // spill_block_unhandled_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5519 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
5520 spill_block_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5521 spill_collect_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5522 spill_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5523
a61af66fc99e Initial load
duke
parents:
diff changeset
5524 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
5525 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5526 tty->print_cr(" state of registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
5527 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5528 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
5529 for (int j = 0; j < _spill_intervals[i]->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5530 tty->print("%d ", _spill_intervals[i]->at(j)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
5531 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5532 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5533 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5535 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5536
a61af66fc99e Initial load
duke
parents:
diff changeset
5537 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5538 int reg_needed_until = MIN2(cur->first_usage(mustHaveRegister), cur->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5539 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5540 assert (reg_needed_until > 0 && reg_needed_until < max_jint, "interval has no use");
a61af66fc99e Initial load
duke
parents:
diff changeset
5541
a61af66fc99e Initial load
duke
parents:
diff changeset
5542 int split_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5543 int use_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5544 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5545 int reg, regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5546
a61af66fc99e Initial load
duke
parents:
diff changeset
5547 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5548 reg = find_locked_double_reg(reg_needed_until, interval_to, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5549 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5550
a61af66fc99e Initial load
duke
parents:
diff changeset
5551 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5552 use_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5553 split_pos = MIN2(_block_pos[reg], _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5554 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5555 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5556 reg = find_locked_reg(reg_needed_until, interval_to, any_reg, cur->assigned_reg(), &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5557 regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5558
a61af66fc99e Initial load
duke
parents:
diff changeset
5559 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5560 use_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5561 split_pos = _block_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5562
a61af66fc99e Initial load
duke
parents:
diff changeset
5563 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5564 if (cur->assigned_reg() != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5565 regHi = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5566 reg = cur->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5567 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5568 regHi = find_locked_reg(reg_needed_until, interval_to, any_reg, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5569 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5570 use_pos = MIN2(use_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5571 split_pos = MIN2(split_pos, _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5573 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5574
a61af66fc99e Initial load
duke
parents:
diff changeset
5575 if (regHi != any_reg && reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5576 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5577 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5578 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5579 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5580 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5581 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5582 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5583 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5584
a61af66fc99e Initial load
duke
parents:
diff changeset
5585 if (reg == any_reg || (_num_phys_regs == 2 && regHi == any_reg) || use_pos <= cur->first_usage(mustHaveRegister)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5586 // the first use of cur is later than the spilling position -> spill cur
a61af66fc99e Initial load
duke
parents:
diff changeset
5587 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
5588
a61af66fc99e Initial load
duke
parents:
diff changeset
5589 if (cur->first_usage(mustHaveRegister) <= cur->from() + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5590 assert(false, "cannot spill interval that is used in first instruction (possible reason: no register found)");
a61af66fc99e Initial load
duke
parents:
diff changeset
5591 // assign a reasonable register and do a bailout in product mode to avoid errors
a61af66fc99e Initial load
duke
parents:
diff changeset
5592 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5593 BAILOUT("LinearScan: no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5595
a61af66fc99e Initial load
duke
parents:
diff changeset
5596 split_and_spill_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5597 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5598 TRACE_LINEAR_SCAN(4, tty->print_cr("decided to use register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5599 assert(reg != any_reg && (_num_phys_regs == 1 || regHi != any_reg), "no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5600 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5601 assert(need_split == false || split_pos > cur->from(), "splitting interval at from");
a61af66fc99e Initial load
duke
parents:
diff changeset
5602
a61af66fc99e Initial load
duke
parents:
diff changeset
5603 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5604 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5605 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5606 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5607 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5608
a61af66fc99e Initial load
duke
parents:
diff changeset
5609 // perform splitting and spilling for all affected intervalls
a61af66fc99e Initial load
duke
parents:
diff changeset
5610 split_and_spill_intersecting_intervals(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5612 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5613
a61af66fc99e Initial load
duke
parents:
diff changeset
5614 bool LinearScanWalker::no_allocation_possible(Interval* cur) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
5615 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5616 // fast calculation of intervals that can never get a register because the
a61af66fc99e Initial load
duke
parents:
diff changeset
5617 // the next instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5618 // Note: this does not work if callee-saved registers are available (e.g. on Sparc)
a61af66fc99e Initial load
duke
parents:
diff changeset
5619
a61af66fc99e Initial load
duke
parents:
diff changeset
5620 // check if this interval is the result of a split operation
a61af66fc99e Initial load
duke
parents:
diff changeset
5621 // (an interval got a register until this position)
a61af66fc99e Initial load
duke
parents:
diff changeset
5622 int pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5623 if ((pos & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5624 // the current instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5625 if (pos < allocator()->max_lir_op_id() && allocator()->has_call(pos + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5626 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
5627
a61af66fc99e Initial load
duke
parents:
diff changeset
5628 // safety check that there is really no register available
a61af66fc99e Initial load
duke
parents:
diff changeset
5629 assert(alloc_free_reg(cur) == false, "found a register for this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5630 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5631 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5632
a61af66fc99e Initial load
duke
parents:
diff changeset
5633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5634 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5635 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5636 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5637
a61af66fc99e Initial load
duke
parents:
diff changeset
5638 void LinearScanWalker::init_vars_for_alloc(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5639 BasicType type = cur->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
5640 _num_phys_regs = LinearScan::num_physical_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5641 _adjacent_regs = LinearScan::requires_adjacent_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5642
a61af66fc99e Initial load
duke
parents:
diff changeset
5643 if (pd_init_regs_for_alloc(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5644 // the appropriate register range was selected.
a61af66fc99e Initial load
duke
parents:
diff changeset
5645 } else if (type == T_FLOAT || type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5646 _first_reg = pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5647 _last_reg = pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5648 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5649 _first_reg = pd_first_cpu_reg;
2002
ac637b7220d1 6985015: C1 needs to support compressed oops
iveresov
parents: 1972
diff changeset
5650 _last_reg = FrameMap::last_cpu_reg();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5652
a61af66fc99e Initial load
duke
parents:
diff changeset
5653 assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5654 assert(0 <= _last_reg && _last_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5655 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5656
a61af66fc99e Initial load
duke
parents:
diff changeset
5657
a61af66fc99e Initial load
duke
parents:
diff changeset
5658 bool LinearScanWalker::is_move(LIR_Op* op, Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5659 if (op->code() != lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5660 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5661 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5662 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5663
a61af66fc99e Initial load
duke
parents:
diff changeset
5664 LIR_Opr in = ((LIR_Op1*)op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5665 LIR_Opr res = ((LIR_Op1*)op)->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5666 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
5667 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5668
a61af66fc99e Initial load
duke
parents:
diff changeset
5669 // optimization (especially for phi functions of nested loops):
a61af66fc99e Initial load
duke
parents:
diff changeset
5670 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5671 void LinearScanWalker::combine_spilled_intervals(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5672 if (cur->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5673 // optimization is only suitable for split parents
a61af66fc99e Initial load
duke
parents:
diff changeset
5674 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5676
a61af66fc99e Initial load
duke
parents:
diff changeset
5677 Interval* register_hint = cur->register_hint(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5678 if (register_hint == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5679 // cur is not the target of a move, otherwise register_hint would be set
a61af66fc99e Initial load
duke
parents:
diff changeset
5680 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5681 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5682 assert(register_hint->is_split_parent(), "register hint must be split parent");
a61af66fc99e Initial load
duke
parents:
diff changeset
5683
a61af66fc99e Initial load
duke
parents:
diff changeset
5684 if (cur->spill_state() != noOptimization || register_hint->spill_state() != noOptimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5685 // combining the stack slots for intervals where spill move optimization is applied
a61af66fc99e Initial load
duke
parents:
diff changeset
5686 // is not benefitial and would cause problems
a61af66fc99e Initial load
duke
parents:
diff changeset
5687 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5688 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5689
a61af66fc99e Initial load
duke
parents:
diff changeset
5690 int begin_pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5691 int end_pos = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5692 if (end_pos > allocator()->max_lir_op_id() || (begin_pos & 1) != 0 || (end_pos & 1) != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5693 // safety check that lir_op_with_id is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
5694 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5695 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5696
a61af66fc99e Initial load
duke
parents:
diff changeset
5697 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
5698 // cur and register_hint are not connected with two moves
a61af66fc99e Initial load
duke
parents:
diff changeset
5699 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5700 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5701
a61af66fc99e Initial load
duke
parents:
diff changeset
5702 Interval* begin_hint = register_hint->split_child_at_op_id(begin_pos, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5703 Interval* end_hint = register_hint->split_child_at_op_id(end_pos, LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5704 if (begin_hint == end_hint || begin_hint->to() != begin_pos || end_hint->from() != end_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5705 // register_hint must be split, otherwise the re-writing of use positions does not work
a61af66fc99e Initial load
duke
parents:
diff changeset
5706 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5708
a61af66fc99e Initial load
duke
parents:
diff changeset
5709 assert(begin_hint->assigned_reg() != any_reg, "must have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5710 assert(end_hint->assigned_reg() == any_reg, "must not have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5711 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
5712 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
5713
a61af66fc99e Initial load
duke
parents:
diff changeset
5714 if (begin_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5715 // 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
5716 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5717 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5718 assert(register_hint->canonical_spill_slot() != -1, "must be set when part of interval was spilled");
a61af66fc99e Initial load
duke
parents:
diff changeset
5719
a61af66fc99e Initial load
duke
parents:
diff changeset
5720 // modify intervals such that cur gets the same stack slot as register_hint
a61af66fc99e Initial load
duke
parents:
diff changeset
5721 // delete use positions to prevent the intervals to get a register at beginning
a61af66fc99e Initial load
duke
parents:
diff changeset
5722 cur->set_canonical_spill_slot(register_hint->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
5723 cur->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5724 end_hint->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5726
a61af66fc99e Initial load
duke
parents:
diff changeset
5727
a61af66fc99e Initial load
duke
parents:
diff changeset
5728 // allocate a physical register or memory location to an interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5729 bool LinearScanWalker::activate_current() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5730 Interval* cur = current();
a61af66fc99e Initial load
duke
parents:
diff changeset
5731 bool result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5732
a61af66fc99e Initial load
duke
parents:
diff changeset
5733 TRACE_LINEAR_SCAN(2, tty->print ("+++++ activating interval "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5734 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
5735
a61af66fc99e Initial load
duke
parents:
diff changeset
5736 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5737 // activating an interval that has a stack slot assigned -> split it at first use position
a61af66fc99e Initial load
duke
parents:
diff changeset
5738 // used for method parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
5739 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
5740
a61af66fc99e Initial load
duke
parents:
diff changeset
5741 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5742 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5743
a61af66fc99e Initial load
duke
parents:
diff changeset
5744 } else if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5745 // activating an interval that must start in a stack slot, but may get a register later
a61af66fc99e Initial load
duke
parents:
diff changeset
5746 // used for lir_roundfp: rounding is done by store to stack and reload later
a61af66fc99e Initial load
duke
parents:
diff changeset
5747 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
5748 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5749
a61af66fc99e Initial load
duke
parents:
diff changeset
5750 allocator()->assign_spill_slot(cur);
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 (cur->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5755 // interval has not assigned register -> normal allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
5756 // (this is the normal case for most intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
5757 TRACE_LINEAR_SCAN(4, tty->print_cr(" normal allocation of register"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5758
a61af66fc99e Initial load
duke
parents:
diff changeset
5759 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5760 combine_spilled_intervals(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5761
a61af66fc99e Initial load
duke
parents:
diff changeset
5762 init_vars_for_alloc(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5763 if (no_allocation_possible(cur) || !alloc_free_reg(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5764 // no empty register available.
a61af66fc99e Initial load
duke
parents:
diff changeset
5765 // split and spill another interval so that this interval gets a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5766 alloc_locked_reg(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5767 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5768
a61af66fc99e Initial load
duke
parents:
diff changeset
5769 // spilled intervals need not be move to active-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5770 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5771 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5772 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5773 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5774
a61af66fc99e Initial load
duke
parents:
diff changeset
5775 // load spilled values that become active from stack slot to register
a61af66fc99e Initial load
duke
parents:
diff changeset
5776 if (cur->insert_move_when_activated()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5777 assert(cur->is_split_child(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5778 assert(cur->current_split_child() != NULL, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5779 assert(cur->current_split_child()->reg_num() != cur->reg_num(), "cannot insert move between same interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5780 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
5781
a61af66fc99e Initial load
duke
parents:
diff changeset
5782 insert_move(cur->from(), cur->current_split_child(), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5783 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5784 cur->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5785
a61af66fc99e Initial load
duke
parents:
diff changeset
5786 return result; // true = interval is moved to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
5787 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5788
a61af66fc99e Initial load
duke
parents:
diff changeset
5789
a61af66fc99e Initial load
duke
parents:
diff changeset
5790 // Implementation of EdgeMoveOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
5791
a61af66fc99e Initial load
duke
parents:
diff changeset
5792 EdgeMoveOptimizer::EdgeMoveOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
5793 _edge_instructions(4),
a61af66fc99e Initial load
duke
parents:
diff changeset
5794 _edge_instructions_idx(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
5795 {
a61af66fc99e Initial load
duke
parents:
diff changeset
5796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5797
a61af66fc99e Initial load
duke
parents:
diff changeset
5798 void EdgeMoveOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5799 EdgeMoveOptimizer optimizer = EdgeMoveOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
5800
a61af66fc99e Initial load
duke
parents:
diff changeset
5801 // ignore the first block in the list (index 0 is not processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
5802 for (int i = code->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5803 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5804
a61af66fc99e Initial load
duke
parents:
diff changeset
5805 if (block->number_of_preds() > 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5806 optimizer.optimize_moves_at_block_end(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5807 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5808 if (block->number_of_sux() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5809 optimizer.optimize_moves_at_block_begin(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5810 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5812 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5813
a61af66fc99e Initial load
duke
parents:
diff changeset
5814
a61af66fc99e Initial load
duke
parents:
diff changeset
5815 // clear all internal data structures
a61af66fc99e Initial load
duke
parents:
diff changeset
5816 void EdgeMoveOptimizer::init_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5817 _edge_instructions.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5818 _edge_instructions_idx.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5819 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5820
a61af66fc99e Initial load
duke
parents:
diff changeset
5821 // append a lir-instruction-list and the index of the current operation in to the list
a61af66fc99e Initial load
duke
parents:
diff changeset
5822 void EdgeMoveOptimizer::append_instructions(LIR_OpList* instructions, int instructions_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5823 _edge_instructions.append(instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
5824 _edge_instructions_idx.append(instructions_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5826
a61af66fc99e Initial load
duke
parents:
diff changeset
5827 // return the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5828 LIR_Op* EdgeMoveOptimizer::instruction_at(int edge) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5829 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5830 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5831
a61af66fc99e Initial load
duke
parents:
diff changeset
5832 if (idx < instructions->length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5833 return instructions->at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5834 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5835 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5836 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5838
a61af66fc99e Initial load
duke
parents:
diff changeset
5839 // removes the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5840 void EdgeMoveOptimizer::remove_cur_instruction(int edge, bool decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5841 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5842 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5843 instructions->remove_at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5844
a61af66fc99e Initial load
duke
parents:
diff changeset
5845 if (decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5846 _edge_instructions_idx.at_put(edge, idx - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5847 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5848 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5849
a61af66fc99e Initial load
duke
parents:
diff changeset
5850
a61af66fc99e Initial load
duke
parents:
diff changeset
5851 bool EdgeMoveOptimizer::operations_different(LIR_Op* op1, LIR_Op* op2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5852 if (op1 == NULL || op2 == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5853 // at least one block is already empty -> no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5854 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5855 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5856
a61af66fc99e Initial load
duke
parents:
diff changeset
5857 if (op1->code() == lir_move && op2->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5858 assert(op1->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5859 assert(op2->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5860 LIR_Op1* move1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5861 LIR_Op1* move2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5862 if (move1->info() == move2->info() && move1->in_opr() == move2->in_opr() && move1->result_opr() == move2->result_opr()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5863 // these moves are exactly equal and can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5864 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5865 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5866
a61af66fc99e Initial load
duke
parents:
diff changeset
5867 } else if (op1->code() == lir_fxch && op2->code() == lir_fxch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5868 assert(op1->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5869 assert(op2->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5870 LIR_Op1* fxch1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5871 LIR_Op1* fxch2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5872 if (fxch1->in_opr()->as_jint() == fxch2->in_opr()->as_jint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5873 // equal FPU stack operations 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_fpop_raw && op2->code() == lir_fpop_raw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5878 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5879 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5880 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5881
a61af66fc99e Initial load
duke
parents:
diff changeset
5882 // no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5883 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5884 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5885
a61af66fc99e Initial load
duke
parents:
diff changeset
5886 void EdgeMoveOptimizer::optimize_moves_at_block_end(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5887 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
5888
a61af66fc99e Initial load
duke
parents:
diff changeset
5889 if (block->is_predecessor(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5890 // currently we can't handle this correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
5891 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5892 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5893
a61af66fc99e Initial load
duke
parents:
diff changeset
5894 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5895 int num_preds = block->number_of_preds();
a61af66fc99e Initial load
duke
parents:
diff changeset
5896 assert(num_preds > 1, "do not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5897 assert(!block->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5898
a61af66fc99e Initial load
duke
parents:
diff changeset
5899 // setup a list with the lir-instructions of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5900 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5901 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5902 BlockBegin* pred = block->pred_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5903 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5904
a61af66fc99e Initial load
duke
parents:
diff changeset
5905 if (pred->number_of_sux() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5906 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
5907 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
5908 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5910
a61af66fc99e Initial load
duke
parents:
diff changeset
5911 assert(pred->number_of_sux() == 1, "can handle only one successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
5912 assert(pred->sux_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
5913 assert(pred_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5914 assert(pred_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5915 assert(pred_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5916
a61af66fc99e Initial load
duke
parents:
diff changeset
5917 if (pred_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5918 // can not optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5919 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5920 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5921
a61af66fc99e Initial load
duke
parents:
diff changeset
5922 // ignore the unconditional branch at the end of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
5923 append_instructions(pred_instructions, pred_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5924 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5925
a61af66fc99e Initial load
duke
parents:
diff changeset
5926
a61af66fc99e Initial load
duke
parents:
diff changeset
5927 // process lir-instructions while all predecessors end with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
5928 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5929 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
5930 for (i = 1; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5931 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5932 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
5933 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5934 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5935 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5936 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5937
a61af66fc99e Initial load
duke
parents:
diff changeset
5938 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
5939
a61af66fc99e Initial load
duke
parents:
diff changeset
5940 // insert the instruction at the beginning of the current block
a61af66fc99e Initial load
duke
parents:
diff changeset
5941 block->lir()->insert_before(1, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
5942
a61af66fc99e Initial load
duke
parents:
diff changeset
5943 // delete the instruction at the end of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5944 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5945 remove_cur_instruction(i, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5946 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5948 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5949
a61af66fc99e Initial load
duke
parents:
diff changeset
5950
a61af66fc99e Initial load
duke
parents:
diff changeset
5951 void EdgeMoveOptimizer::optimize_moves_at_block_begin(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5952 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
5953
a61af66fc99e Initial load
duke
parents:
diff changeset
5954 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5955 int num_sux = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
5956
a61af66fc99e Initial load
duke
parents:
diff changeset
5957 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5958
a61af66fc99e Initial load
duke
parents:
diff changeset
5959 assert(num_sux == 2, "method should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5960 assert(cur_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5961 assert(cur_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5962 assert(cur_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5963
a61af66fc99e Initial load
duke
parents:
diff changeset
5964 if (cur_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5965 // can no optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5966 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5968
a61af66fc99e Initial load
duke
parents:
diff changeset
5969 LIR_Op* branch = cur_instructions->at(cur_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5970 if (branch->info() != NULL || (branch->code() != lir_branch && branch->code() != lir_cond_float_branch)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5971 // not a valid case for optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5972 // currently, only blocks that end with two branches (conditional branch followed
a61af66fc99e Initial load
duke
parents:
diff changeset
5973 // by unconditional branch) are optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5974 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5975 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5976
a61af66fc99e Initial load
duke
parents:
diff changeset
5977 // now it is guaranteed that the block ends with two branch instructions.
a61af66fc99e Initial load
duke
parents:
diff changeset
5978 // the instructions are inserted at the end of the block before these two branches
a61af66fc99e Initial load
duke
parents:
diff changeset
5979 int insert_idx = cur_instructions->length() - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5980
a61af66fc99e Initial load
duke
parents:
diff changeset
5981 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5982 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
5983 for (i = insert_idx - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5984 LIR_Op* op = cur_instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5985 if ((op->code() == lir_branch || op->code() == lir_cond_float_branch) && ((LIR_OpBranch*)op)->block() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5986 assert(false, "block with two successors can have only two branch instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
5987 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5988 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5989 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5990
a61af66fc99e Initial load
duke
parents:
diff changeset
5991 // setup a list with the lir-instructions of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
5992 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5993 BlockBegin* sux = block->sux_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5994 LIR_OpList* sux_instructions = sux->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5995
a61af66fc99e Initial load
duke
parents:
diff changeset
5996 assert(sux_instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
5997
a61af66fc99e Initial load
duke
parents:
diff changeset
5998 if (sux->number_of_preds() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5999 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
6000 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
6001 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
6002 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6003 assert(sux->pred_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
6004 assert(!sux->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
6005
a61af66fc99e Initial load
duke
parents:
diff changeset
6006 // ignore the label at the beginning of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
6007 append_instructions(sux_instructions, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6008 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6009
a61af66fc99e Initial load
duke
parents:
diff changeset
6010 // process lir-instructions while all successors begin with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6011 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6012 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6013 for (i = 1; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6014 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6015 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
6016 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
6017 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
6018 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6020
a61af66fc99e Initial load
duke
parents:
diff changeset
6021 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
6022
a61af66fc99e Initial load
duke
parents:
diff changeset
6023 // insert instruction at end of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
6024 block->lir()->insert_before(insert_idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
6025 insert_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6026
a61af66fc99e Initial load
duke
parents:
diff changeset
6027 // delete the instructions at the beginning of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
6028 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6029 remove_cur_instruction(i, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
6030 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6031 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6032 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6033
a61af66fc99e Initial load
duke
parents:
diff changeset
6034
a61af66fc99e Initial load
duke
parents:
diff changeset
6035 // Implementation of ControlFlowOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
6036
a61af66fc99e Initial load
duke
parents:
diff changeset
6037 ControlFlowOptimizer::ControlFlowOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
6038 _original_preds(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
6039 {
a61af66fc99e Initial load
duke
parents:
diff changeset
6040 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6041
a61af66fc99e Initial load
duke
parents:
diff changeset
6042 void ControlFlowOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6043 ControlFlowOptimizer optimizer = ControlFlowOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
6044
a61af66fc99e Initial load
duke
parents:
diff changeset
6045 // push the OSR entry block to the end so that we're not jumping over it.
a61af66fc99e Initial load
duke
parents:
diff changeset
6046 BlockBegin* osr_entry = code->at(0)->end()->as_Base()->osr_entry();
a61af66fc99e Initial load
duke
parents:
diff changeset
6047 if (osr_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6048 int index = osr_entry->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
6049 assert(code->at(index) == osr_entry, "wrong index");
a61af66fc99e Initial load
duke
parents:
diff changeset
6050 code->remove_at(index);
a61af66fc99e Initial load
duke
parents:
diff changeset
6051 code->append(osr_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
6052 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6053
a61af66fc99e Initial load
duke
parents:
diff changeset
6054 optimizer.reorder_short_loops(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6055 optimizer.delete_empty_blocks(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6056 optimizer.delete_unnecessary_jumps(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6057 optimizer.delete_jumps_to_return(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
6058 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6059
a61af66fc99e Initial load
duke
parents:
diff changeset
6060 void ControlFlowOptimizer::reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6061 int i = header_idx + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6062 int max_end = MIN2(header_idx + ShortLoopSize, code->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
6063 while (i < max_end && code->at(i)->loop_depth() >= header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6064 i++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6065 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6066
a61af66fc99e Initial load
duke
parents:
diff changeset
6067 if (i == code->length() || code->at(i)->loop_depth() < header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6068 int end_idx = i - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6069 BlockBegin* end_block = code->at(end_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
6070
a61af66fc99e Initial load
duke
parents:
diff changeset
6071 if (end_block->number_of_sux() == 1 && end_block->sux_at(0) == header_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6072 // short loop from header_idx to end_idx found -> reorder blocks such that
a61af66fc99e Initial load
duke
parents:
diff changeset
6073 // the header_block is the last block instead of the first block of the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
6074 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
6075 end_idx - header_idx + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
6076 header_block->block_id(), end_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6077
a61af66fc99e Initial load
duke
parents:
diff changeset
6078 for (int j = header_idx; j < end_idx; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6079 code->at_put(j, code->at(j + 1));
a61af66fc99e Initial load
duke
parents:
diff changeset
6080 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6081 code->at_put(end_idx, header_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6082
a61af66fc99e Initial load
duke
parents:
diff changeset
6083 // correct the flags so that any loop alignment occurs in the right place.
a61af66fc99e Initial load
duke
parents:
diff changeset
6084 assert(code->at(end_idx)->is_set(BlockBegin::backward_branch_target_flag), "must be backward branch target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6085 code->at(end_idx)->clear(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6086 code->at(header_idx)->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6087 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6088 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6089 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6090
a61af66fc99e Initial load
duke
parents:
diff changeset
6091 void ControlFlowOptimizer::reorder_short_loops(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6092 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6093 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6094
a61af66fc99e Initial load
duke
parents:
diff changeset
6095 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6096 reorder_short_loop(code, block, i);
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 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6102
a61af66fc99e Initial load
duke
parents:
diff changeset
6103 // only blocks with exactly one successor can be deleted. Such blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6104 // must always end with an unconditional branch to this successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6105 bool ControlFlowOptimizer::can_delete_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6106 if (block->number_of_sux() != 1 || block->number_of_exception_handlers() != 0 || block->is_entry_block()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6107 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6109
a61af66fc99e Initial load
duke
parents:
diff changeset
6110 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6111
a61af66fc99e Initial load
duke
parents:
diff changeset
6112 assert(instructions->length() >= 2, "block must have label and branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6113 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6114 assert(instructions->last()->as_OpBranch() != NULL, "last instrcution must always be a branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6115 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "branch must be unconditional");
a61af66fc99e Initial load
duke
parents:
diff changeset
6116 assert(instructions->last()->as_OpBranch()->block() == block->sux_at(0), "branch target must be the successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
6117
a61af66fc99e Initial load
duke
parents:
diff changeset
6118 // block must have exactly one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6119
a61af66fc99e Initial load
duke
parents:
diff changeset
6120 if (instructions->length() == 2 && instructions->last()->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6121 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6123 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6124 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6125
a61af66fc99e Initial load
duke
parents:
diff changeset
6126 // substitute branch targets in all branch-instructions of this blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6127 void ControlFlowOptimizer::substitute_branch_target(BlockBegin* block, BlockBegin* target_from, BlockBegin* target_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6128 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
6129
a61af66fc99e Initial load
duke
parents:
diff changeset
6130 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6131
a61af66fc99e Initial load
duke
parents:
diff changeset
6132 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6133 for (int i = instructions->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6134 LIR_Op* op = instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6135
a61af66fc99e Initial load
duke
parents:
diff changeset
6136 if (op->code() == lir_branch || op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6137 assert(op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6138 LIR_OpBranch* branch = (LIR_OpBranch*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6139
a61af66fc99e Initial load
duke
parents:
diff changeset
6140 if (branch->block() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6141 branch->change_block(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6143 if (branch->ublock() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6144 branch->change_ublock(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6145 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6149
a61af66fc99e Initial load
duke
parents:
diff changeset
6150 void ControlFlowOptimizer::delete_empty_blocks(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6151 int old_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6152 int new_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6153 int num_blocks = code->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
6154
a61af66fc99e Initial load
duke
parents:
diff changeset
6155 while (old_pos < num_blocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6156 BlockBegin* block = code->at(old_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6157
a61af66fc99e Initial load
duke
parents:
diff changeset
6158 if (can_delete_block(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6159 BlockBegin* new_target = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6160
a61af66fc99e Initial load
duke
parents:
diff changeset
6161 // propagate backward branch target flag for correct code alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
6162 if (block->is_set(BlockBegin::backward_branch_target_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6163 new_target->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6164 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6165
a61af66fc99e Initial load
duke
parents:
diff changeset
6166 // collect a list with all predecessors that contains each predecessor only once
a61af66fc99e Initial load
duke
parents:
diff changeset
6167 // the predecessors of cur are changed during the substitution, so a copy of the
a61af66fc99e Initial load
duke
parents:
diff changeset
6168 // predecessor list is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6169 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6170 _original_preds.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6171 for (j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6172 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6173 if (_original_preds.index_of(pred) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6174 _original_preds.append(pred);
a61af66fc99e Initial load
duke
parents:
diff changeset
6175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6176 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6177
a61af66fc99e Initial load
duke
parents:
diff changeset
6178 for (j = _original_preds.length() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6179 BlockBegin* pred = _original_preds.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6180 substitute_branch_target(pred, block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6181 pred->substitute_sux(block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6182 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6183 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6184 // adjust position of this block in the block list if blocks before
a61af66fc99e Initial load
duke
parents:
diff changeset
6185 // have been deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6186 if (new_pos != old_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6187 code->at_put(new_pos, code->at(old_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
6188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6189 new_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6191 old_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6192 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6193 code->truncate(new_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6194
a61af66fc99e Initial load
duke
parents:
diff changeset
6195 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6197
a61af66fc99e Initial load
duke
parents:
diff changeset
6198 void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6199 // skip the last block because there a branch is always necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6200 for (int i = code->length() - 2; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6201 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6202 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6203
a61af66fc99e Initial load
duke
parents:
diff changeset
6204 LIR_Op* last_op = instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6205 if (last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6206 assert(last_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6207 LIR_OpBranch* last_branch = (LIR_OpBranch*)last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6208
a61af66fc99e Initial load
duke
parents:
diff changeset
6209 assert(last_branch->block() != NULL, "last branch must always have a block as target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6210 assert(last_branch->label() == last_branch->block()->label(), "must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
6211
a61af66fc99e Initial load
duke
parents:
diff changeset
6212 if (last_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6213 if (last_branch->block() == code->at(i + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6214
a61af66fc99e Initial load
duke
parents:
diff changeset
6215 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
6216
a61af66fc99e Initial load
duke
parents:
diff changeset
6217 // delete last branch instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6218 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6219
a61af66fc99e Initial load
duke
parents:
diff changeset
6220 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6221 LIR_Op* prev_op = instructions->at(instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6222 if (prev_op->code() == lir_branch || prev_op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6223 assert(prev_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6224 LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6225
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6226 if (prev_branch->stub() == NULL) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6227
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6228 LIR_Op2* prev_cmp = NULL;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6229
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6230 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
6231 prev_op = instructions->at(j);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6232 if (prev_op->code() == lir_cmp) {
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6233 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
6234 prev_cmp = (LIR_Op2*)prev_op;
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6235 assert(prev_branch->cond() == prev_cmp->condition(), "should be the same");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6236 }
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6237 }
8860
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6238 assert(prev_cmp != NULL, "should have found comp instruction for branch");
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6239 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
6240
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6241 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
6242
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6243 // eliminate a conditional branch to the immediate successor
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6244 prev_branch->change_block(last_branch->block());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6245 prev_branch->negate_cond();
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6246 prev_cmp->set_condition(prev_branch->cond());
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6247 instructions->truncate(instructions->length() - 1);
46f6f063b272 7153771: array bound check elimination for c1
roland
parents: 6842
diff changeset
6248 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6249 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6252 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6254 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6255
a61af66fc99e Initial load
duke
parents:
diff changeset
6256 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6258
a61af66fc99e Initial load
duke
parents:
diff changeset
6259 void ControlFlowOptimizer::delete_jumps_to_return(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6260 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6261 BitMap return_converted(BlockBegin::number_of_blocks());
a61af66fc99e Initial load
duke
parents:
diff changeset
6262 return_converted.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6263 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6264
a61af66fc99e Initial load
duke
parents:
diff changeset
6265 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6266 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6267 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6268 LIR_Op* cur_last_op = cur_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6269
a61af66fc99e Initial load
duke
parents:
diff changeset
6270 assert(cur_instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6271 if (cur_instructions->length() == 2 && cur_last_op->code() == lir_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6272 // the block contains only a label and a return
a61af66fc99e Initial load
duke
parents:
diff changeset
6273 // if a predecessor ends with an unconditional jump to this block, then the jump
a61af66fc99e Initial load
duke
parents:
diff changeset
6274 // can be replaced with a return instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6275 //
a61af66fc99e Initial load
duke
parents:
diff changeset
6276 // Note: the original block with only a return statement cannot be deleted completely
a61af66fc99e Initial load
duke
parents:
diff changeset
6277 // because the predecessors might have other (conditional) jumps to this block
a61af66fc99e Initial load
duke
parents:
diff changeset
6278 // -> this may lead to unnecesary return instructions in the final code
a61af66fc99e Initial load
duke
parents:
diff changeset
6279
a61af66fc99e Initial load
duke
parents:
diff changeset
6280 assert(cur_last_op->info() == NULL, "return instructions do not have debug information");
a61af66fc99e Initial load
duke
parents:
diff changeset
6281 assert(block->number_of_sux() == 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
6282 (return_converted.at(block->block_id()) && block->number_of_sux() == 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
6283 "blocks that end with return must not have successors");
a61af66fc99e Initial load
duke
parents:
diff changeset
6284
a61af66fc99e Initial load
duke
parents:
diff changeset
6285 assert(cur_last_op->as_Op1() != NULL, "return must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
6286 LIR_Opr return_opr = ((LIR_Op1*)cur_last_op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6287
a61af66fc99e Initial load
duke
parents:
diff changeset
6288 for (int j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6289 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6290 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6291 LIR_Op* pred_last_op = pred_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6292
a61af66fc99e Initial load
duke
parents:
diff changeset
6293 if (pred_last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6294 assert(pred_last_op->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6295 LIR_OpBranch* pred_last_branch = (LIR_OpBranch*)pred_last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6296
a61af66fc99e Initial load
duke
parents:
diff changeset
6297 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
6298 // replace the jump to a return with a direct return
a61af66fc99e Initial load
duke
parents:
diff changeset
6299 // Note: currently the edge between the blocks is not deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6300 pred_instructions->at_put(pred_instructions->length() - 1, new LIR_Op1(lir_return, return_opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
6301 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6302 return_converted.set_bit(pred->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
6303 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6304 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6306 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6307 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6308 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6310
a61af66fc99e Initial load
duke
parents:
diff changeset
6311
a61af66fc99e Initial load
duke
parents:
diff changeset
6312 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6313 void ControlFlowOptimizer::verify(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6314 for (int i = 0; i < code->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6315 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6316 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6317
a61af66fc99e Initial load
duke
parents:
diff changeset
6318 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6319 for (j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6320 LIR_OpBranch* op_branch = instructions->at(j)->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6321
a61af66fc99e Initial load
duke
parents:
diff changeset
6322 if (op_branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6323 assert(op_branch->block() == NULL || code->index_of(op_branch->block()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6324 assert(op_branch->ublock() == NULL || code->index_of(op_branch->ublock()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6326 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6327
a61af66fc99e Initial load
duke
parents:
diff changeset
6328 for (j = 0; j < block->number_of_sux() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6329 BlockBegin* sux = block->sux_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6330 assert(code->index_of(sux) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6331 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6332
a61af66fc99e Initial load
duke
parents:
diff changeset
6333 for (j = 0; j < block->number_of_preds() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6334 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6335 assert(code->index_of(pred) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6336 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6338 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6339 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6340
a61af66fc99e Initial load
duke
parents:
diff changeset
6341
a61af66fc99e Initial load
duke
parents:
diff changeset
6342 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
6343
a61af66fc99e Initial load
duke
parents:
diff changeset
6344 // Implementation of LinearStatistic
a61af66fc99e Initial load
duke
parents:
diff changeset
6345
a61af66fc99e Initial load
duke
parents:
diff changeset
6346 const char* LinearScanStatistic::counter_name(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6347 switch (counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6348 case counter_method: return "compiled methods";
a61af66fc99e Initial load
duke
parents:
diff changeset
6349 case counter_fpu_method: return "methods using fpu";
a61af66fc99e Initial load
duke
parents:
diff changeset
6350 case counter_loop_method: return "methods with loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6351 case counter_exception_method:return "methods with xhandler";
a61af66fc99e Initial load
duke
parents:
diff changeset
6352
a61af66fc99e Initial load
duke
parents:
diff changeset
6353 case counter_loop: return "loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6354 case counter_block: return "blocks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6355 case counter_loop_block: return "blocks inside loop";
a61af66fc99e Initial load
duke
parents:
diff changeset
6356 case counter_exception_block: return "exception handler entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6357 case counter_interval: return "intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6358 case counter_fixed_interval: return "fixed intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6359 case counter_range: return "ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6360 case counter_fixed_range: return "fixed ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6361 case counter_use_pos: return "use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6362 case counter_fixed_use_pos: return "fixed use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6363 case counter_spill_slots: return "spill slots";
a61af66fc99e Initial load
duke
parents:
diff changeset
6364
a61af66fc99e Initial load
duke
parents:
diff changeset
6365 // counter for classes of lir instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
6366 case counter_instruction: return "total instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6367 case counter_label: return "labels";
a61af66fc99e Initial load
duke
parents:
diff changeset
6368 case counter_entry: return "method entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6369 case counter_return: return "method returns";
a61af66fc99e Initial load
duke
parents:
diff changeset
6370 case counter_call: return "method calls";
a61af66fc99e Initial load
duke
parents:
diff changeset
6371 case counter_move: return "moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6372 case counter_cmp: return "compare";
a61af66fc99e Initial load
duke
parents:
diff changeset
6373 case counter_cond_branch: return "conditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6374 case counter_uncond_branch: return "unconditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6375 case counter_stub_branch: return "branches to stub";
a61af66fc99e Initial load
duke
parents:
diff changeset
6376 case counter_alu: return "artithmetic + logic";
a61af66fc99e Initial load
duke
parents:
diff changeset
6377 case counter_alloc: return "allocations";
a61af66fc99e Initial load
duke
parents:
diff changeset
6378 case counter_sync: return "synchronisation";
a61af66fc99e Initial load
duke
parents:
diff changeset
6379 case counter_throw: return "throw";
a61af66fc99e Initial load
duke
parents:
diff changeset
6380 case counter_unwind: return "unwind";
a61af66fc99e Initial load
duke
parents:
diff changeset
6381 case counter_typecheck: return "type+null-checks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6382 case counter_fpu_stack: return "fpu-stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6383 case counter_misc_inst: return "other instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6384 case counter_other_inst: return "misc. instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6385
a61af66fc99e Initial load
duke
parents:
diff changeset
6386 // counter for different types of moves
a61af66fc99e Initial load
duke
parents:
diff changeset
6387 case counter_move_total: return "total moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6388 case counter_move_reg_reg: return "register->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6389 case counter_move_reg_stack: return "register->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6390 case counter_move_stack_reg: return "stack->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6391 case counter_move_stack_stack:return "stack->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6392 case counter_move_reg_mem: return "register->memory";
a61af66fc99e Initial load
duke
parents:
diff changeset
6393 case counter_move_mem_reg: return "memory->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6394 case counter_move_const_any: return "constant->any";
a61af66fc99e Initial load
duke
parents:
diff changeset
6395
a61af66fc99e Initial load
duke
parents:
diff changeset
6396 case blank_line_1: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6397 case blank_line_2: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6398
a61af66fc99e Initial load
duke
parents:
diff changeset
6399 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6402
a61af66fc99e Initial load
duke
parents:
diff changeset
6403 LinearScanStatistic::Counter LinearScanStatistic::base_counter(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6404 if (counter_idx == counter_fpu_method || counter_idx == counter_loop_method || counter_idx == counter_exception_method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6405 return counter_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
6406 } else if (counter_idx == counter_loop_block || counter_idx == counter_exception_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6407 return counter_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
6408 } else if (counter_idx >= counter_instruction && counter_idx <= counter_other_inst) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6409 return counter_instruction;
a61af66fc99e Initial load
duke
parents:
diff changeset
6410 } else if (counter_idx >= counter_move_total && counter_idx <= counter_move_const_any) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6411 return counter_move_total;
a61af66fc99e Initial load
duke
parents:
diff changeset
6412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6413 return invalid_counter;
a61af66fc99e Initial load
duke
parents:
diff changeset
6414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6415
a61af66fc99e Initial load
duke
parents:
diff changeset
6416 LinearScanStatistic::LinearScanStatistic() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6417 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6418 _counters_sum[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6419 _counters_max[i] = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6421
a61af66fc99e Initial load
duke
parents:
diff changeset
6422 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6423
a61af66fc99e Initial load
duke
parents:
diff changeset
6424 // add the method-local numbers to the total sum
a61af66fc99e Initial load
duke
parents:
diff changeset
6425 void LinearScanStatistic::sum_up(LinearScanStatistic &method_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6426 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6427 _counters_sum[i] += method_statistic._counters_sum[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
6428 _counters_max[i] = MAX2(_counters_max[i], method_statistic._counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6431
a61af66fc99e Initial load
duke
parents:
diff changeset
6432 void LinearScanStatistic::print(const char* title) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6433 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6434 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6435 tty->print_cr("***** LinearScan statistic - %s *****", title);
a61af66fc99e Initial load
duke
parents:
diff changeset
6436
a61af66fc99e Initial load
duke
parents:
diff changeset
6437 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6438 if (_counters_sum[i] > 0 || _counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6439 tty->print("%25s: %8d", counter_name(i), _counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6440
a61af66fc99e Initial load
duke
parents:
diff changeset
6441 if (base_counter(i) != invalid_counter) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6442 tty->print(" (%5.1f%%) ", _counters_sum[i] * 100.0 / _counters_sum[base_counter(i)]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6443 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6444 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
6445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6446
a61af66fc99e Initial load
duke
parents:
diff changeset
6447 if (_counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6448 tty->print("%8d", _counters_max[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6451 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6452 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6453 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6454 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6455
a61af66fc99e Initial load
duke
parents:
diff changeset
6456 void LinearScanStatistic::collect(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6457 inc_counter(counter_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6458 if (allocator->has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6459 inc_counter(counter_fpu_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6460 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6461 if (allocator->num_loops() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6462 inc_counter(counter_loop_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6464 inc_counter(counter_loop, allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6465 inc_counter(counter_spill_slots, allocator->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
6466
a61af66fc99e Initial load
duke
parents:
diff changeset
6467 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
6468 for (i = 0; i < allocator->interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6469 Interval* cur = allocator->interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6470
a61af66fc99e Initial load
duke
parents:
diff changeset
6471 if (cur != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6472 inc_counter(counter_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6473 inc_counter(counter_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6474 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6475 inc_counter(counter_fixed_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6476 inc_counter(counter_fixed_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6477 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6478
a61af66fc99e Initial load
duke
parents:
diff changeset
6479 Range* range = cur->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
6480 while (range != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6481 inc_counter(counter_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6482 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6483 inc_counter(counter_fixed_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6484 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6485 range = range->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
6486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6489
a61af66fc99e Initial load
duke
parents:
diff changeset
6490 bool has_xhandlers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6491 // Note: only count blocks that are in code-emit order
a61af66fc99e Initial load
duke
parents:
diff changeset
6492 for (i = 0; i < allocator->ir()->code()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6493 BlockBegin* cur = allocator->ir()->code()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6494
a61af66fc99e Initial load
duke
parents:
diff changeset
6495 inc_counter(counter_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6496 if (cur->loop_depth() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6497 inc_counter(counter_loop_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6499 if (cur->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6500 inc_counter(counter_exception_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6501 has_xhandlers = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6502 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6503
a61af66fc99e Initial load
duke
parents:
diff changeset
6504 LIR_OpList* instructions = cur->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6505 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6506 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6507
a61af66fc99e Initial load
duke
parents:
diff changeset
6508 inc_counter(counter_instruction);
a61af66fc99e Initial load
duke
parents:
diff changeset
6509
a61af66fc99e Initial load
duke
parents:
diff changeset
6510 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6511 case lir_label: inc_counter(counter_label); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6512 case lir_std_entry:
a61af66fc99e Initial load
duke
parents:
diff changeset
6513 case lir_osr_entry: inc_counter(counter_entry); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6514 case lir_return: inc_counter(counter_return); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6515
a61af66fc99e Initial load
duke
parents:
diff changeset
6516 case lir_rtcall:
a61af66fc99e Initial load
duke
parents:
diff changeset
6517 case lir_static_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6518 case lir_optvirtual_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6519 case lir_virtual_call: inc_counter(counter_call); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6520
a61af66fc99e Initial load
duke
parents:
diff changeset
6521 case lir_move: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6522 inc_counter(counter_move);
a61af66fc99e Initial load
duke
parents:
diff changeset
6523 inc_counter(counter_move_total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6524
a61af66fc99e Initial load
duke
parents:
diff changeset
6525 LIR_Opr in = op->as_Op1()->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6526 LIR_Opr res = op->as_Op1()->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6527 if (in->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6528 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6529 inc_counter(counter_move_reg_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6530 } else if (res->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6531 inc_counter(counter_move_reg_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6532 } else if (res->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6533 inc_counter(counter_move_reg_mem);
a61af66fc99e Initial load
duke
parents:
diff changeset
6534 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6535 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6536 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6537 } else if (in->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6538 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6539 inc_counter(counter_move_stack_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6540 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6541 inc_counter(counter_move_stack_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6543 } else if (in->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6544 assert(res->is_register(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
6545 inc_counter(counter_move_mem_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6546 } else if (in->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6547 inc_counter(counter_move_const_any);
a61af66fc99e Initial load
duke
parents:
diff changeset
6548 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6549 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6551 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6553
a61af66fc99e Initial load
duke
parents:
diff changeset
6554 case lir_cmp: inc_counter(counter_cmp); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6555
a61af66fc99e Initial load
duke
parents:
diff changeset
6556 case lir_branch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6557 case lir_cond_float_branch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6558 LIR_OpBranch* branch = op->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6559 if (branch->block() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6560 inc_counter(counter_stub_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6561 } else if (branch->cond() == lir_cond_always) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6562 inc_counter(counter_uncond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6563 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6564 inc_counter(counter_cond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6565 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6566 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6567 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6568
a61af66fc99e Initial load
duke
parents:
diff changeset
6569 case lir_neg:
a61af66fc99e Initial load
duke
parents:
diff changeset
6570 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
6571 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
6572 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
6573 case lir_mul_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6574 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
6575 case lir_div_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6576 case lir_rem:
a61af66fc99e Initial load
duke
parents:
diff changeset
6577 case lir_sqrt:
a61af66fc99e Initial load
duke
parents:
diff changeset
6578 case lir_sin:
a61af66fc99e Initial load
duke
parents:
diff changeset
6579 case lir_cos:
a61af66fc99e Initial load
duke
parents:
diff changeset
6580 case lir_abs:
a61af66fc99e Initial load
duke
parents:
diff changeset
6581 case lir_log10:
a61af66fc99e Initial load
duke
parents:
diff changeset
6582 case lir_log:
6084
6759698e3140 7133857: exp() and pow() should use the x87 ISA on x86
roland
parents: 5906
diff changeset
6583 case lir_pow:
6759698e3140 7133857: exp() and pow() should use the x87 ISA on x86
roland
parents: 5906
diff changeset
6584 case lir_exp:
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6585 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
6586 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
6587 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
6588 case lir_shl:
a61af66fc99e Initial load
duke
parents:
diff changeset
6589 case lir_shr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6590 case lir_ushr: inc_counter(counter_alu); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6591
a61af66fc99e Initial load
duke
parents:
diff changeset
6592 case lir_alloc_object:
a61af66fc99e Initial load
duke
parents:
diff changeset
6593 case lir_alloc_array: inc_counter(counter_alloc); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6594
a61af66fc99e Initial load
duke
parents:
diff changeset
6595 case lir_monaddr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6596 case lir_lock:
a61af66fc99e Initial load
duke
parents:
diff changeset
6597 case lir_unlock: inc_counter(counter_sync); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6598
a61af66fc99e Initial load
duke
parents:
diff changeset
6599 case lir_throw: inc_counter(counter_throw); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6600
a61af66fc99e Initial load
duke
parents:
diff changeset
6601 case lir_unwind: inc_counter(counter_unwind); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6602
a61af66fc99e Initial load
duke
parents:
diff changeset
6603 case lir_null_check:
a61af66fc99e Initial load
duke
parents:
diff changeset
6604 case lir_leal:
a61af66fc99e Initial load
duke
parents:
diff changeset
6605 case lir_instanceof:
a61af66fc99e Initial load
duke
parents:
diff changeset
6606 case lir_checkcast:
a61af66fc99e Initial load
duke
parents:
diff changeset
6607 case lir_store_check: inc_counter(counter_typecheck); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6608
a61af66fc99e Initial load
duke
parents:
diff changeset
6609 case lir_fpop_raw:
a61af66fc99e Initial load
duke
parents:
diff changeset
6610 case lir_fxch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6611 case lir_fld: inc_counter(counter_fpu_stack); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6612
a61af66fc99e Initial load
duke
parents:
diff changeset
6613 case lir_nop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6614 case lir_push:
a61af66fc99e Initial load
duke
parents:
diff changeset
6615 case lir_pop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6616 case lir_convert:
a61af66fc99e Initial load
duke
parents:
diff changeset
6617 case lir_roundfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6618 case lir_cmove: inc_counter(counter_misc_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6619
a61af66fc99e Initial load
duke
parents:
diff changeset
6620 default: inc_counter(counter_other_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6623 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6624
a61af66fc99e Initial load
duke
parents:
diff changeset
6625 if (has_xhandlers) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6626 inc_counter(counter_exception_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6627 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6629
a61af66fc99e Initial load
duke
parents:
diff changeset
6630 void LinearScanStatistic::compute(LinearScan* allocator, LinearScanStatistic &global_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6631 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6632
a61af66fc99e Initial load
duke
parents:
diff changeset
6633 LinearScanStatistic local_statistic = LinearScanStatistic();
a61af66fc99e Initial load
duke
parents:
diff changeset
6634
a61af66fc99e Initial load
duke
parents:
diff changeset
6635 local_statistic.collect(allocator);
a61af66fc99e Initial load
duke
parents:
diff changeset
6636 global_statistic.sum_up(local_statistic);
a61af66fc99e Initial load
duke
parents:
diff changeset
6637
a61af66fc99e Initial load
duke
parents:
diff changeset
6638 if (TraceLinearScanLevel > 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6639 local_statistic.print("current local statistic");
a61af66fc99e Initial load
duke
parents:
diff changeset
6640 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6641 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6642 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6643
a61af66fc99e Initial load
duke
parents:
diff changeset
6644
a61af66fc99e Initial load
duke
parents:
diff changeset
6645 // Implementation of LinearTimers
a61af66fc99e Initial load
duke
parents:
diff changeset
6646
a61af66fc99e Initial load
duke
parents:
diff changeset
6647 LinearScanTimers::LinearScanTimers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6648 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6649 timer(i)->reset();
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 const char* LinearScanTimers::timer_name(int idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6654 switch (idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6655 case timer_do_nothing: return "Nothing (Time Check)";
a61af66fc99e Initial load
duke
parents:
diff changeset
6656 case timer_number_instructions: return "Number Instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6657 case timer_compute_local_live_sets: return "Local Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6658 case timer_compute_global_live_sets: return "Global Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6659 case timer_build_intervals: return "Build Intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6660 case timer_sort_intervals_before: return "Sort Intervals Before";
a61af66fc99e Initial load
duke
parents:
diff changeset
6661 case timer_allocate_registers: return "Allocate Registers";
a61af66fc99e Initial load
duke
parents:
diff changeset
6662 case timer_resolve_data_flow: return "Resolve Data Flow";
a61af66fc99e Initial load
duke
parents:
diff changeset
6663 case timer_sort_intervals_after: return "Sort Intervals After";
a61af66fc99e Initial load
duke
parents:
diff changeset
6664 case timer_eliminate_spill_moves: return "Spill optimization";
a61af66fc99e Initial load
duke
parents:
diff changeset
6665 case timer_assign_reg_num: return "Assign Reg Num";
a61af66fc99e Initial load
duke
parents:
diff changeset
6666 case timer_allocate_fpu_stack: return "Allocate FPU Stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6667 case timer_optimize_lir: return "Optimize LIR";
a61af66fc99e Initial load
duke
parents:
diff changeset
6668 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6669 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6671
a61af66fc99e Initial load
duke
parents:
diff changeset
6672 void LinearScanTimers::begin_method() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6673 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6674 // reset all timers to measure only current method
a61af66fc99e Initial load
duke
parents:
diff changeset
6675 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6676 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6677 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6678 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6679 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6680
a61af66fc99e Initial load
duke
parents:
diff changeset
6681 void LinearScanTimers::end_method(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6682 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6683
a61af66fc99e Initial load
duke
parents:
diff changeset
6684 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6685 double total = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6686 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6687 total += timer(i)->seconds() - c;
a61af66fc99e Initial load
duke
parents:
diff changeset
6688 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6689
a61af66fc99e Initial load
duke
parents:
diff changeset
6690 if (total >= 0.0005) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6691 // print all information in one line for automatic processing
a61af66fc99e Initial load
duke
parents:
diff changeset
6692 tty->print("@"); allocator->compilation()->method()->print_name();
a61af66fc99e Initial load
duke
parents:
diff changeset
6693
a61af66fc99e Initial load
duke
parents:
diff changeset
6694 tty->print("@ %d ", allocator->compilation()->method()->code_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
6695 tty->print("@ %d ", allocator->block_at(allocator->block_count() - 1)->last_lir_instruction_id() / 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6696 tty->print("@ %d ", allocator->block_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6697 tty->print("@ %d ", allocator->num_virtual_regs());
a61af66fc99e Initial load
duke
parents:
diff changeset
6698 tty->print("@ %d ", allocator->interval_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6699 tty->print("@ %d ", allocator->_num_calls);
a61af66fc99e Initial load
duke
parents:
diff changeset
6700 tty->print("@ %d ", allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6701
a61af66fc99e Initial load
duke
parents:
diff changeset
6702 tty->print("@ %6.6f ", total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6703 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6704 tty->print("@ %4.1f ", ((timer(i)->seconds() - c) / total) * 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
6705 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6706 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6710
a61af66fc99e Initial load
duke
parents:
diff changeset
6711 void LinearScanTimers::print(double total_time) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6712 if (TimeLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6713 // correction value: sum of dummy-timer that only measures the time that
a61af66fc99e Initial load
duke
parents:
diff changeset
6714 // is necesary to start and stop itself
a61af66fc99e Initial load
duke
parents:
diff changeset
6715 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6716
a61af66fc99e Initial load
duke
parents:
diff changeset
6717 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6718 double t = timer(i)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6719 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
6720 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6722 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6723
a61af66fc99e Initial load
duke
parents:
diff changeset
6724 #endif // #ifndef PRODUCT