annotate src/share/vm/c1/c1_LinearScan.cpp @ 1721:413ad0331a0c

6977924: Changes for 6975078 produce build error with certain gcc versions Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error. Reviewed-by: jcoomes, ysr, phh
author johnc
date Wed, 18 Aug 2010 10:59:06 -0700
parents 126ea7725993
children 87b64980e2f1
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
2 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1397
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include "incls/_c1_LinearScan.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28
a61af66fc99e Initial load
duke
parents:
diff changeset
29 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
30
a61af66fc99e Initial load
duke
parents:
diff changeset
31 static LinearScanStatistic _stat_before_alloc;
a61af66fc99e Initial load
duke
parents:
diff changeset
32 static LinearScanStatistic _stat_after_asign;
a61af66fc99e Initial load
duke
parents:
diff changeset
33 static LinearScanStatistic _stat_final;
a61af66fc99e Initial load
duke
parents:
diff changeset
34
a61af66fc99e Initial load
duke
parents:
diff changeset
35 static LinearScanTimers _total_timer;
a61af66fc99e Initial load
duke
parents:
diff changeset
36
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // helper macro for short definition of timer
a61af66fc99e Initial load
duke
parents:
diff changeset
38 #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
39
a61af66fc99e Initial load
duke
parents:
diff changeset
40 // helper macro for short definition of trace-output inside code
a61af66fc99e Initial load
duke
parents:
diff changeset
41 #define TRACE_LINEAR_SCAN(level, code) \
a61af66fc99e Initial load
duke
parents:
diff changeset
42 if (TraceLinearScanLevel >= level) { \
a61af66fc99e Initial load
duke
parents:
diff changeset
43 code; \
a61af66fc99e Initial load
duke
parents:
diff changeset
44 }
a61af66fc99e Initial load
duke
parents:
diff changeset
45
a61af66fc99e Initial load
duke
parents:
diff changeset
46 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 #define TIME_LINEAR_SCAN(timer_name)
a61af66fc99e Initial load
duke
parents:
diff changeset
49 #define TRACE_LINEAR_SCAN(level, code)
a61af66fc99e Initial load
duke
parents:
diff changeset
50
a61af66fc99e Initial load
duke
parents:
diff changeset
51 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
52
a61af66fc99e Initial load
duke
parents:
diff changeset
53 // Map BasicType to spill size in 32-bit words, matching VMReg's notion of words
a61af66fc99e Initial load
duke
parents:
diff changeset
54 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
55 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 0, 1, -1};
a61af66fc99e Initial load
duke
parents:
diff changeset
56 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
57 static int type2spill_size[T_CONFLICT+1]={ -1, 0, 0, 0, 1, 1, 1, 2, 1, 1, 1, 2, 1, 1, 0, 1, -1};
a61af66fc99e Initial load
duke
parents:
diff changeset
58 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
59
a61af66fc99e Initial load
duke
parents:
diff changeset
60
a61af66fc99e Initial load
duke
parents:
diff changeset
61 // Implementation of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 LinearScan::LinearScan(IR* ir, LIRGenerator* gen, FrameMap* frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
64 : _compilation(ir->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
65 , _ir(ir)
a61af66fc99e Initial load
duke
parents:
diff changeset
66 , _gen(gen)
a61af66fc99e Initial load
duke
parents:
diff changeset
67 , _frame_map(frame_map)
a61af66fc99e Initial load
duke
parents:
diff changeset
68 , _num_virtual_regs(gen->max_virtual_register_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
69 , _has_fpu_registers(false)
a61af66fc99e Initial load
duke
parents:
diff changeset
70 , _num_calls(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
71 , _max_spills(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
72 , _unused_spill_slot(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
73 , _intervals(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
74 , _new_intervals_from_allocation(new IntervalList())
a61af66fc99e Initial load
duke
parents:
diff changeset
75 , _sorted_intervals(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
76 , _lir_ops(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
77 , _block_of_op(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
78 , _has_info(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
79 , _has_call(0)
a61af66fc99e Initial load
duke
parents:
diff changeset
80 , _scope_value_cache(0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
81 , _interval_in_loop(0, 0) // initialized later with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
82 , _cached_blocks(*ir->linear_scan_order())
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
83 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
84 , _fpu_stack_allocator(NULL)
a61af66fc99e Initial load
duke
parents:
diff changeset
85 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
86 {
a61af66fc99e Initial load
duke
parents:
diff changeset
87 assert(this->ir() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
88 assert(this->compilation() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
89 assert(this->gen() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
90 assert(this->frame_map() != NULL, "check if valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
91 }
a61af66fc99e Initial load
duke
parents:
diff changeset
92
a61af66fc99e Initial load
duke
parents:
diff changeset
93
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // ********** functions for converting LIR-Operands to register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
95 //
a61af66fc99e Initial load
duke
parents:
diff changeset
96 // Emulate a flat register file comprising physical integer registers,
a61af66fc99e Initial load
duke
parents:
diff changeset
97 // physical floating-point registers and virtual registers, in that order.
a61af66fc99e Initial load
duke
parents:
diff changeset
98 // Virtual registers already have appropriate numbers, since V0 is
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // the number of physical registers.
a61af66fc99e Initial load
duke
parents:
diff changeset
100 // Returns -1 for hi word if opr is a single word operand.
a61af66fc99e Initial load
duke
parents:
diff changeset
101 //
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // Note: the inverse operation (calculating an operand for register numbers)
a61af66fc99e Initial load
duke
parents:
diff changeset
103 // is done in calc_operand_for_interval()
a61af66fc99e Initial load
duke
parents:
diff changeset
104
a61af66fc99e Initial load
duke
parents:
diff changeset
105 int LinearScan::reg_num(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
107
a61af66fc99e Initial load
duke
parents:
diff changeset
108 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
109 assert(opr->vreg_number() >= nof_regs, "found a virtual register with a fixed-register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
110 return opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
111 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
112 return opr->cpu_regnr();
a61af66fc99e Initial load
duke
parents:
diff changeset
113 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 return opr->cpu_regnrLo();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
115 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
116 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
117 return opr->fpu_regnr() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
118 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
119 return opr->fpu_regnrLo() + pd_first_xmm_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
120 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
121 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
122 return opr->fpu_regnr() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
123 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
124 return opr->fpu_regnrLo() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
125 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
127 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
130
a61af66fc99e Initial load
duke
parents:
diff changeset
131 int LinearScan::reg_numHi(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
132 assert(opr->is_register(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
133
a61af66fc99e Initial load
duke
parents:
diff changeset
134 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
135 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
136 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
137 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
139 return opr->cpu_regnrHi();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
140 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
141 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
142 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
143 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
144 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
145 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
146 } else if (opr->is_single_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
148 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
149 return opr->fpu_regnrHi() + pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
150 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
152 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
155
a61af66fc99e Initial load
duke
parents:
diff changeset
156
a61af66fc99e Initial load
duke
parents:
diff changeset
157 // ********** functions for classification of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
158
a61af66fc99e Initial load
duke
parents:
diff changeset
159 bool LinearScan::is_precolored_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
160 return i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
162
a61af66fc99e Initial load
duke
parents:
diff changeset
163 bool LinearScan::is_virtual_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
164 return i->reg_num() >= LIR_OprDesc::vreg_base;
a61af66fc99e Initial load
duke
parents:
diff changeset
165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
166
a61af66fc99e Initial load
duke
parents:
diff changeset
167 bool LinearScan::is_precolored_cpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 return i->reg_num() < LinearScan::nof_cpu_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
169 }
a61af66fc99e Initial load
duke
parents:
diff changeset
170
a61af66fc99e Initial load
duke
parents:
diff changeset
171 bool LinearScan::is_virtual_cpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
172 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
173 return i->reg_num() >= LIR_OprDesc::vreg_base;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
174 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
175 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
176 #endif // __SOFTFP__ or E500V2
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 bool LinearScan::is_precolored_fpu_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
180 return i->reg_num() >= LinearScan::nof_cpu_regs && i->reg_num() < LinearScan::nof_regs;
a61af66fc99e Initial load
duke
parents:
diff changeset
181 }
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 bool LinearScan::is_virtual_fpu_interval(const Interval* i) {
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
184 #if defined(__SOFTFP__) || defined(E500V2)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
185 return false;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
186 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
187 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
188 #endif // __SOFTFP__ or E500V2
0
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_in_fpu_register(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
192 // fixed intervals not needed for FPU stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
193 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
194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
195
a61af66fc99e Initial load
duke
parents:
diff changeset
196 bool LinearScan::is_oop_interval(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
197 // fixed intervals never contain oops
a61af66fc99e Initial load
duke
parents:
diff changeset
198 return i->reg_num() >= nof_regs && i->type() == T_OBJECT;
a61af66fc99e Initial load
duke
parents:
diff changeset
199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
200
a61af66fc99e Initial load
duke
parents:
diff changeset
201
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // ********** General helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
203
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // compute next unused stack index that can be used for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
205 int LinearScan::allocate_spill_slot(bool double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 int spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
207 if (double_word) {
a61af66fc99e Initial load
duke
parents:
diff changeset
208 if ((_max_spills & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
209 // alignment of double-word values
a61af66fc99e Initial load
duke
parents:
diff changeset
210 // the hole because of the alignment is filled with the next single-word value
a61af66fc99e Initial load
duke
parents:
diff changeset
211 assert(_unused_spill_slot == -1, "wasting a spill slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
212 _unused_spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
213 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
215 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
216 _max_spills += 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
217
a61af66fc99e Initial load
duke
parents:
diff changeset
218 } else if (_unused_spill_slot != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
219 // re-use hole that was the result of a previous double-word alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
220 spill_slot = _unused_spill_slot;
a61af66fc99e Initial load
duke
parents:
diff changeset
221 _unused_spill_slot = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
222
a61af66fc99e Initial load
duke
parents:
diff changeset
223 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
224 spill_slot = _max_spills;
a61af66fc99e Initial load
duke
parents:
diff changeset
225 _max_spills++;
a61af66fc99e Initial load
duke
parents:
diff changeset
226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 int result = spill_slot + LinearScan::nof_regs + frame_map()->argcount();
a61af66fc99e Initial load
duke
parents:
diff changeset
229
a61af66fc99e Initial load
duke
parents:
diff changeset
230 // the class OopMapValue uses only 11 bits for storing the name of the
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // oop location. So a stack slot bigger than 2^11 leads to an overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
232 // that is not reported in product builds. Prevent this by checking the
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // spill slot here (altough this value and the later used location name
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // are slightly different)
a61af66fc99e Initial load
duke
parents:
diff changeset
235 if (result > 2000) {
a61af66fc99e Initial load
duke
parents:
diff changeset
236 bailout("too many stack slots used");
a61af66fc99e Initial load
duke
parents:
diff changeset
237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
238
a61af66fc99e Initial load
duke
parents:
diff changeset
239 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
241
a61af66fc99e Initial load
duke
parents:
diff changeset
242 void LinearScan::assign_spill_slot(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 // assign the canonical spill slot of the parent (if a part of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
244 // is already spilled) or allocate a new spill slot
a61af66fc99e Initial load
duke
parents:
diff changeset
245 if (it->canonical_spill_slot() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
246 it->assign_reg(it->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
247 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 int spill = allocate_spill_slot(type2spill_size[it->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
249 it->set_canonical_spill_slot(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
250 it->assign_reg(spill);
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
a61af66fc99e Initial load
duke
parents:
diff changeset
252 }
a61af66fc99e Initial load
duke
parents:
diff changeset
253
a61af66fc99e Initial load
duke
parents:
diff changeset
254 void LinearScan::propagate_spill_slots() {
a61af66fc99e Initial load
duke
parents:
diff changeset
255 if (!frame_map()->finalize_frame(max_spills())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
256 bailout("frame too large");
a61af66fc99e Initial load
duke
parents:
diff changeset
257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
259
a61af66fc99e Initial load
duke
parents:
diff changeset
260 // create a new interval with a predefined reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // (only used for parent intervals that are created during the building phase)
a61af66fc99e Initial load
duke
parents:
diff changeset
262 Interval* LinearScan::create_interval(int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
263 assert(_intervals.at(reg_num) == NULL, "overwriting exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
264
a61af66fc99e Initial load
duke
parents:
diff changeset
265 Interval* interval = new Interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
266 _intervals.at_put(reg_num, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
267
a61af66fc99e Initial load
duke
parents:
diff changeset
268 // assign register number for precolored intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
269 if (reg_num < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
270 interval->assign_reg(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
272 return interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
274
a61af66fc99e Initial load
duke
parents:
diff changeset
275 // assign a new reg_num to the interval and append it to the list of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // (only used for child intervals that are created during register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
277 void LinearScan::append_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
278 it->set_reg_num(_intervals.length());
a61af66fc99e Initial load
duke
parents:
diff changeset
279 _intervals.append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
280 _new_intervals_from_allocation->append(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
281 }
a61af66fc99e Initial load
duke
parents:
diff changeset
282
a61af66fc99e Initial load
duke
parents:
diff changeset
283 // copy the vreg-flags if an interval is split
a61af66fc99e Initial load
duke
parents:
diff changeset
284 void LinearScan::copy_register_flags(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
285 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::byte_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
286 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::byte_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
288 if (gen()->is_vreg_flag_set(from->reg_num(), LIRGenerator::callee_saved)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
289 gen()->set_vreg_flag(to->reg_num(), LIRGenerator::callee_saved);
a61af66fc99e Initial load
duke
parents:
diff changeset
290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
291
a61af66fc99e Initial load
duke
parents:
diff changeset
292 // Note: do not copy the must_start_in_memory flag because it is not necessary for child
a61af66fc99e Initial load
duke
parents:
diff changeset
293 // intervals (only the very beginning of the interval must be in memory)
a61af66fc99e Initial load
duke
parents:
diff changeset
294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
295
a61af66fc99e Initial load
duke
parents:
diff changeset
296
a61af66fc99e Initial load
duke
parents:
diff changeset
297 // ********** spill move optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
298 // eliminate moves from register to stack if stack slot is known to be correct
a61af66fc99e Initial load
duke
parents:
diff changeset
299
a61af66fc99e Initial load
duke
parents:
diff changeset
300 // called during building of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
301 void LinearScan::change_spill_definition_pos(Interval* interval, int def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
302 assert(interval->is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
303
a61af66fc99e Initial load
duke
parents:
diff changeset
304 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
305 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
306 assert(interval->spill_definition_pos() == -1, "must no be set before");
a61af66fc99e Initial load
duke
parents:
diff changeset
307 interval->set_spill_definition_pos(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
308 interval->set_spill_state(oneDefinitionFound);
a61af66fc99e Initial load
duke
parents:
diff changeset
309 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
310
a61af66fc99e Initial load
duke
parents:
diff changeset
311 case oneDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
312 assert(def_pos <= interval->spill_definition_pos(), "positions are processed in reverse order when intervals are created");
a61af66fc99e Initial load
duke
parents:
diff changeset
313 if (def_pos < interval->spill_definition_pos() - 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
314 // second definition found, so no spill optimization possible for this interval
a61af66fc99e Initial load
duke
parents:
diff changeset
315 interval->set_spill_state(noOptimization);
a61af66fc99e Initial load
duke
parents:
diff changeset
316 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // two consecutive definitions (because of two-operand LIR form)
a61af66fc99e Initial load
duke
parents:
diff changeset
318 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
319 }
a61af66fc99e Initial load
duke
parents:
diff changeset
320 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
321
a61af66fc99e Initial load
duke
parents:
diff changeset
322 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
323 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
324 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
325
a61af66fc99e Initial load
duke
parents:
diff changeset
326 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
327 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
328 }
a61af66fc99e Initial load
duke
parents:
diff changeset
329 }
a61af66fc99e Initial load
duke
parents:
diff changeset
330
a61af66fc99e Initial load
duke
parents:
diff changeset
331 // called during register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
332 void LinearScan::change_spill_state(Interval* interval, int spill_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
333 switch (interval->spill_state()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
334 case oneDefinitionFound: {
a61af66fc99e Initial load
duke
parents:
diff changeset
335 int def_loop_depth = block_of_op_with_id(interval->spill_definition_pos())->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
336 int spill_loop_depth = block_of_op_with_id(spill_pos)->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
337
a61af66fc99e Initial load
duke
parents:
diff changeset
338 if (def_loop_depth < spill_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
339 // the loop depth of the spilling position is higher then the loop depth
a61af66fc99e Initial load
duke
parents:
diff changeset
340 // at the definition of the interval -> move write to memory out of loop
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // by storing at definitin of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
342 interval->set_spill_state(storeAtDefinition);
a61af66fc99e Initial load
duke
parents:
diff changeset
343 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
344 // the interval is currently spilled only once, so for now there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
345 // reason to store the interval at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
346 interval->set_spill_state(oneMoveInserted);
a61af66fc99e Initial load
duke
parents:
diff changeset
347 }
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
a61af66fc99e Initial load
duke
parents:
diff changeset
351 case oneMoveInserted: {
a61af66fc99e Initial load
duke
parents:
diff changeset
352 // the interval is spilled more then once, so it is better to store it to
a61af66fc99e Initial load
duke
parents:
diff changeset
353 // memory at the definition
a61af66fc99e Initial load
duke
parents:
diff changeset
354 interval->set_spill_state(storeAtDefinition);
a61af66fc99e Initial load
duke
parents:
diff changeset
355 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
357
a61af66fc99e Initial load
duke
parents:
diff changeset
358 case storeAtDefinition:
a61af66fc99e Initial load
duke
parents:
diff changeset
359 case startInMemory:
a61af66fc99e Initial load
duke
parents:
diff changeset
360 case noOptimization:
a61af66fc99e Initial load
duke
parents:
diff changeset
361 case noDefinitionFound:
a61af66fc99e Initial load
duke
parents:
diff changeset
362 // nothing to do
a61af66fc99e Initial load
duke
parents:
diff changeset
363 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
364
a61af66fc99e Initial load
duke
parents:
diff changeset
365 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
366 assert(false, "other states not allowed at this time");
a61af66fc99e Initial load
duke
parents:
diff changeset
367 }
a61af66fc99e Initial load
duke
parents:
diff changeset
368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
369
a61af66fc99e Initial load
duke
parents:
diff changeset
370
a61af66fc99e Initial load
duke
parents:
diff changeset
371 bool LinearScan::must_store_at_definition(const Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
372 return i->is_split_parent() && i->spill_state() == storeAtDefinition;
a61af66fc99e Initial load
duke
parents:
diff changeset
373 }
a61af66fc99e Initial load
duke
parents:
diff changeset
374
a61af66fc99e Initial load
duke
parents:
diff changeset
375 // called once before asignment of register numbers
a61af66fc99e Initial load
duke
parents:
diff changeset
376 void LinearScan::eliminate_spill_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
377 TIME_LINEAR_SCAN(timer_eliminate_spill_moves);
a61af66fc99e Initial load
duke
parents:
diff changeset
378 TRACE_LINEAR_SCAN(3, tty->print_cr("***** Eliminating unnecessary spill moves"));
a61af66fc99e Initial load
duke
parents:
diff changeset
379
a61af66fc99e Initial load
duke
parents:
diff changeset
380 // collect all intervals that must be stored after their definion.
a61af66fc99e Initial load
duke
parents:
diff changeset
381 // the list is sorted by Interval::spill_definition_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
382 Interval* interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
383 Interval* temp_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
384 create_unhandled_lists(&interval, &temp_list, must_store_at_definition, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
385
a61af66fc99e Initial load
duke
parents:
diff changeset
386 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
387 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
388 Interval* temp = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
389 while (temp != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
390 assert(temp->spill_definition_pos() > 0, "invalid spill definition pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
391 if (prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
392 assert(temp->from() >= prev->from(), "intervals not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
393 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
394 }
a61af66fc99e Initial load
duke
parents:
diff changeset
395
a61af66fc99e Initial load
duke
parents:
diff changeset
396 assert(temp->canonical_spill_slot() >= LinearScan::nof_regs, "interval has no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
397 assert(temp->spill_definition_pos() >= temp->from(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
398 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
399
a61af66fc99e Initial load
duke
parents:
diff changeset
400 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
401
a61af66fc99e Initial load
duke
parents:
diff changeset
402 temp = temp->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
403 }
a61af66fc99e Initial load
duke
parents:
diff changeset
404 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
405
a61af66fc99e Initial load
duke
parents:
diff changeset
406 LIR_InsertionBuffer insertion_buffer;
a61af66fc99e Initial load
duke
parents:
diff changeset
407 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
408 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
409 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
410 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
411 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
412 bool has_new = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
413
a61af66fc99e Initial load
duke
parents:
diff changeset
414 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
415 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
416 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
417 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419 if (op_id == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
420 // remove move from register to stack if the stack slot is guaranteed to be correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
421 // only moves that have been inserted by LinearScan can be removed.
a61af66fc99e Initial load
duke
parents:
diff changeset
422 assert(op->code() == lir_move, "only moves can have a op_id of -1");
a61af66fc99e Initial load
duke
parents:
diff changeset
423 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
424 assert(op->as_Op1()->result_opr()->is_virtual(), "LinearScan inserts only moves to virtual registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
425
a61af66fc99e Initial load
duke
parents:
diff changeset
426 LIR_Op1* op1 = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
427 Interval* interval = interval_at(op1->result_opr()->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429 if (interval->assigned_reg() >= LinearScan::nof_regs && interval->always_in_memory()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
430 // move target is a stack slot that is always correct, so eliminate instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
431 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
432 instructions->at_put(j, NULL); // NULL-instructions are deleted by assign_reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
433 }
a61af66fc99e Initial load
duke
parents:
diff changeset
434
a61af66fc99e Initial load
duke
parents:
diff changeset
435 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
436 // insert move from register to stack just after the beginning of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
437 assert(interval == Interval::end() || interval->spill_definition_pos() >= op_id, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
438 assert(interval == Interval::end() || (interval->is_split_parent() && interval->spill_state() == storeAtDefinition), "invalid interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
439
a61af66fc99e Initial load
duke
parents:
diff changeset
440 while (interval != Interval::end() && interval->spill_definition_pos() == op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
441 if (!has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
442 // prepare insertion buffer (appended when all instructions of the block are processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
443 insertion_buffer.init(block->lir());
a61af66fc99e Initial load
duke
parents:
diff changeset
444 has_new = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
445 }
a61af66fc99e Initial load
duke
parents:
diff changeset
446
a61af66fc99e Initial load
duke
parents:
diff changeset
447 LIR_Opr from_opr = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
448 LIR_Opr to_opr = canonical_spill_opr(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
449 assert(from_opr->is_fixed_cpu() || from_opr->is_fixed_fpu(), "from operand must be a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
450 assert(to_opr->is_stack(), "to operand must be a stack slot");
a61af66fc99e Initial load
duke
parents:
diff changeset
451
a61af66fc99e Initial load
duke
parents:
diff changeset
452 insertion_buffer.move(j, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
453 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
454
a61af66fc99e Initial load
duke
parents:
diff changeset
455 interval = interval->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
458 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
459
a61af66fc99e Initial load
duke
parents:
diff changeset
460 if (has_new) {
a61af66fc99e Initial load
duke
parents:
diff changeset
461 block->lir()->append(&insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
462 }
a61af66fc99e Initial load
duke
parents:
diff changeset
463 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
464
a61af66fc99e Initial load
duke
parents:
diff changeset
465 assert(interval == Interval::end(), "missed an interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
466 }
a61af66fc99e Initial load
duke
parents:
diff changeset
467
a61af66fc99e Initial load
duke
parents:
diff changeset
468
a61af66fc99e Initial load
duke
parents:
diff changeset
469 // ********** Phase 1: number all instructions in all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
470 // Compute depth-first and linear scan block orders, and number LIR_Op nodes for linear scan.
a61af66fc99e Initial load
duke
parents:
diff changeset
471
a61af66fc99e Initial load
duke
parents:
diff changeset
472 void LinearScan::number_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
473 {
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // dummy-timer to measure the cost of the timer itself
a61af66fc99e Initial load
duke
parents:
diff changeset
475 // (this time is then subtracted from all other timers to get the real value)
a61af66fc99e Initial load
duke
parents:
diff changeset
476 TIME_LINEAR_SCAN(timer_do_nothing);
a61af66fc99e Initial load
duke
parents:
diff changeset
477 }
a61af66fc99e Initial load
duke
parents:
diff changeset
478 TIME_LINEAR_SCAN(timer_number_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
479
a61af66fc99e Initial load
duke
parents:
diff changeset
480 // Assign IDs to LIR nodes and build a mapping, lir_ops, from ID to LIR_Op node.
a61af66fc99e Initial load
duke
parents:
diff changeset
481 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
482 int num_instructions = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
483 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
484 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 num_instructions += block_at(i)->lir()->instructions_list()->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
487
a61af66fc99e Initial load
duke
parents:
diff changeset
488 // initialize with correct length
a61af66fc99e Initial load
duke
parents:
diff changeset
489 _lir_ops = LIR_OpArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
490 _block_of_op = BlockBeginArray(num_instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
491
a61af66fc99e Initial load
duke
parents:
diff changeset
492 int op_id = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
493 int idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
494
a61af66fc99e Initial load
duke
parents:
diff changeset
495 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
496 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
497 block->set_first_lir_instruction_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
498 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
499
a61af66fc99e Initial load
duke
parents:
diff changeset
500 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
501 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
502 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
503 op->set_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
504
a61af66fc99e Initial load
duke
parents:
diff changeset
505 _lir_ops.at_put(idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
506 _block_of_op.at_put(idx, block);
a61af66fc99e Initial load
duke
parents:
diff changeset
507 assert(lir_op_with_id(op_id) == op, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
508
a61af66fc99e Initial load
duke
parents:
diff changeset
509 idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
510 op_id += 2; // numbering of lir_ops by two
a61af66fc99e Initial load
duke
parents:
diff changeset
511 }
a61af66fc99e Initial load
duke
parents:
diff changeset
512 block->set_last_lir_instruction_id(op_id - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
513 }
a61af66fc99e Initial load
duke
parents:
diff changeset
514 assert(idx == num_instructions, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
515 assert(idx * 2 == op_id, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
516
a61af66fc99e Initial load
duke
parents:
diff changeset
517 _has_call = BitMap(num_instructions); _has_call.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
518 _has_info = BitMap(num_instructions); _has_info.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
520
a61af66fc99e Initial load
duke
parents:
diff changeset
521
a61af66fc99e Initial load
duke
parents:
diff changeset
522 // ********** Phase 2: compute local live sets separately for each block
a61af66fc99e Initial load
duke
parents:
diff changeset
523 // (sets live_gen and live_kill for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
524
a61af66fc99e Initial load
duke
parents:
diff changeset
525 void LinearScan::set_live_gen_kill(Value value, LIR_Op* op, BitMap& live_gen, BitMap& live_kill) {
a61af66fc99e Initial load
duke
parents:
diff changeset
526 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
527 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529 // check some asumptions about debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
530 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
531 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
532 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
533
a61af66fc99e Initial load
duke
parents:
diff changeset
534 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
535 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
536 int reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
537 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
538 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
539 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
540 }
a61af66fc99e Initial load
duke
parents:
diff changeset
541 }
a61af66fc99e Initial load
duke
parents:
diff changeset
542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
543
a61af66fc99e Initial load
duke
parents:
diff changeset
544
a61af66fc99e Initial load
duke
parents:
diff changeset
545 void LinearScan::compute_local_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
546 TIME_LINEAR_SCAN(timer_compute_local_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
547
a61af66fc99e Initial load
duke
parents:
diff changeset
548 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
549 int live_size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
550 bool local_has_fpu_registers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
551 int local_num_calls = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
552 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
553
a61af66fc99e Initial load
duke
parents:
diff changeset
554 BitMap2D local_interval_in_loop = BitMap2D(_num_virtual_regs, num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
555 local_interval_in_loop.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
556
a61af66fc99e Initial load
duke
parents:
diff changeset
557 // iterate all blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
558 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
559 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
560
a61af66fc99e Initial load
duke
parents:
diff changeset
561 BitMap live_gen(live_size); live_gen.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
562 BitMap live_kill(live_size); live_kill.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
563
a61af66fc99e Initial load
duke
parents:
diff changeset
564 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
565 // Phi functions at the begin of an exception handler are
a61af66fc99e Initial load
duke
parents:
diff changeset
566 // implicitly defined (= killed) at the beginning of the block.
a61af66fc99e Initial load
duke
parents:
diff changeset
567 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
568 live_kill.set_bit(phi->operand()->vreg_number())
a61af66fc99e Initial load
duke
parents:
diff changeset
569 );
a61af66fc99e Initial load
duke
parents:
diff changeset
570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
571
a61af66fc99e Initial load
duke
parents:
diff changeset
572 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
573 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
574
a61af66fc99e Initial load
duke
parents:
diff changeset
575 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
576 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
577 for (int j = 1; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
578 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
579
a61af66fc99e Initial load
duke
parents:
diff changeset
580 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
581 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
582
a61af66fc99e Initial load
duke
parents:
diff changeset
583 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
584 _has_call.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
585 local_num_calls++;
a61af66fc99e Initial load
duke
parents:
diff changeset
586 }
a61af66fc99e Initial load
duke
parents:
diff changeset
587 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
588 _has_info.set_bit(op->id() >> 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
589 }
a61af66fc99e Initial load
duke
parents:
diff changeset
590
a61af66fc99e Initial load
duke
parents:
diff changeset
591 // iterate input operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
592 int k, n, reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
593 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
594 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
595 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
596 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
597
a61af66fc99e Initial load
duke
parents:
diff changeset
598 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
599 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
600 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
601 if (!live_kill.at(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
602 live_gen.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
603 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
604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
605 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
606 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
607 }
a61af66fc99e Initial load
duke
parents:
diff changeset
608 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
609 }
a61af66fc99e Initial load
duke
parents:
diff changeset
610
a61af66fc99e Initial load
duke
parents:
diff changeset
611 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
613 // they need not be processed in live sets.
a61af66fc99e Initial load
duke
parents:
diff changeset
614 // this is checked by these assertions to be sure about it.
a61af66fc99e Initial load
duke
parents:
diff changeset
615 // the entry block may have incoming values in registers, which is ok.
a61af66fc99e Initial load
duke
parents:
diff changeset
616 if (!opr->is_virtual_register() && block != ir()->start()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
617 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
618 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
619 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
621 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
622 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
623 assert(live_kill.at(reg), "using fixed register that is not defined in this block");
a61af66fc99e Initial load
duke
parents:
diff changeset
624 }
a61af66fc99e Initial load
duke
parents:
diff changeset
625 }
a61af66fc99e Initial load
duke
parents:
diff changeset
626 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
627 }
a61af66fc99e Initial load
duke
parents:
diff changeset
628
a61af66fc99e Initial load
duke
parents:
diff changeset
629 // Add uses of live locals from interpreter's point of view for proper debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
630 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
631 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
632 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
633 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
634 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
635 set_live_gen_kill(value, op, live_gen, live_kill)
a61af66fc99e Initial load
duke
parents:
diff changeset
636 );
a61af66fc99e Initial load
duke
parents:
diff changeset
637 }
a61af66fc99e Initial load
duke
parents:
diff changeset
638
a61af66fc99e Initial load
duke
parents:
diff changeset
639 // iterate temp operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
640 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
641 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
642 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
643 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
644
a61af66fc99e Initial load
duke
parents:
diff changeset
645 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
646 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
647 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
648 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
649 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
650 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
651 }
a61af66fc99e Initial load
duke
parents:
diff changeset
652 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
653 }
a61af66fc99e Initial load
duke
parents:
diff changeset
654
a61af66fc99e Initial load
duke
parents:
diff changeset
655 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
656 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
657 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
658 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
659 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
660 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
661 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
662 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
663 }
a61af66fc99e Initial load
duke
parents:
diff changeset
664 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
665 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
667 }
a61af66fc99e Initial load
duke
parents:
diff changeset
668 }
a61af66fc99e Initial load
duke
parents:
diff changeset
669 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
671
a61af66fc99e Initial load
duke
parents:
diff changeset
672 // iterate output operands of instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
673 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
674 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
675 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
676 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
677
a61af66fc99e Initial load
duke
parents:
diff changeset
678 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
679 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
680 reg = opr->vreg_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
681 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
682 if (block->loop_index() >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
683 local_interval_in_loop.set_bit(reg, block->loop_index());
a61af66fc99e Initial load
duke
parents:
diff changeset
684 }
a61af66fc99e Initial load
duke
parents:
diff changeset
685 local_has_fpu_registers = local_has_fpu_registers || opr->is_virtual_fpu();
a61af66fc99e Initial load
duke
parents:
diff changeset
686 }
a61af66fc99e Initial load
duke
parents:
diff changeset
687
a61af66fc99e Initial load
duke
parents:
diff changeset
688 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
689 // fixed intervals are never live at block boundaries, so
a61af66fc99e Initial load
duke
parents:
diff changeset
690 // they need not be processed in live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
691 // process them only in debug mode so that this can be checked
a61af66fc99e Initial load
duke
parents:
diff changeset
692 if (!opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
693 reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
694 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
695 live_kill.set_bit(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
696 }
a61af66fc99e Initial load
duke
parents:
diff changeset
697 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
698 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
699 live_kill.set_bit(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
700 }
a61af66fc99e Initial load
duke
parents:
diff changeset
701 }
a61af66fc99e Initial load
duke
parents:
diff changeset
702 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
704 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
705
a61af66fc99e Initial load
duke
parents:
diff changeset
706 block->set_live_gen (live_gen);
a61af66fc99e Initial load
duke
parents:
diff changeset
707 block->set_live_kill(live_kill);
a61af66fc99e Initial load
duke
parents:
diff changeset
708 block->set_live_in (BitMap(live_size)); block->live_in().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
709 block->set_live_out (BitMap(live_size)); block->live_out().clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
710
a61af66fc99e Initial load
duke
parents:
diff changeset
711 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
712 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
713 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
714
a61af66fc99e Initial load
duke
parents:
diff changeset
715 // propagate local calculated information into LinearScan object
a61af66fc99e Initial load
duke
parents:
diff changeset
716 _has_fpu_registers = local_has_fpu_registers;
a61af66fc99e Initial load
duke
parents:
diff changeset
717 compilation()->set_has_fpu_code(local_has_fpu_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
718
a61af66fc99e Initial load
duke
parents:
diff changeset
719 _num_calls = local_num_calls;
a61af66fc99e Initial load
duke
parents:
diff changeset
720 _interval_in_loop = local_interval_in_loop;
a61af66fc99e Initial load
duke
parents:
diff changeset
721 }
a61af66fc99e Initial load
duke
parents:
diff changeset
722
a61af66fc99e Initial load
duke
parents:
diff changeset
723
a61af66fc99e Initial load
duke
parents:
diff changeset
724 // ********** Phase 3: perform a backward dataflow analysis to compute global live sets
a61af66fc99e Initial load
duke
parents:
diff changeset
725 // (sets live_in and live_out for each block)
a61af66fc99e Initial load
duke
parents:
diff changeset
726
a61af66fc99e Initial load
duke
parents:
diff changeset
727 void LinearScan::compute_global_live_sets() {
a61af66fc99e Initial load
duke
parents:
diff changeset
728 TIME_LINEAR_SCAN(timer_compute_global_live_sets);
a61af66fc99e Initial load
duke
parents:
diff changeset
729
a61af66fc99e Initial load
duke
parents:
diff changeset
730 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
731 bool change_occurred;
a61af66fc99e Initial load
duke
parents:
diff changeset
732 bool change_occurred_in_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
733 int iteration_count = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
734 BitMap live_out(live_set_size()); live_out.clear(); // scratch set for calculations
a61af66fc99e Initial load
duke
parents:
diff changeset
735
a61af66fc99e Initial load
duke
parents:
diff changeset
736 // Perform a backward dataflow analysis to compute live_out and live_in for each block.
a61af66fc99e Initial load
duke
parents:
diff changeset
737 // The loop is executed until a fixpoint is reached (no changes in an iteration)
a61af66fc99e Initial load
duke
parents:
diff changeset
738 // Exception handlers must be processed because not all live values are
a61af66fc99e Initial load
duke
parents:
diff changeset
739 // present in the state array, e.g. because of global value numbering
a61af66fc99e Initial load
duke
parents:
diff changeset
740 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
741 change_occurred = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
742
a61af66fc99e Initial load
duke
parents:
diff changeset
743 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
744 for (int i = num_blocks - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
745 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
746
a61af66fc99e Initial load
duke
parents:
diff changeset
747 change_occurred_in_block = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
748
a61af66fc99e Initial load
duke
parents:
diff changeset
749 // live_out(block) is the union of live_in(sux), for successors sux of block
a61af66fc99e Initial load
duke
parents:
diff changeset
750 int n = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
751 int e = block->number_of_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
752 if (n + e > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
753 // block has successors
a61af66fc99e Initial load
duke
parents:
diff changeset
754 if (n > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
755 live_out.set_from(block->sux_at(0)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
756 for (int j = 1; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
757 live_out.set_union(block->sux_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
758 }
a61af66fc99e Initial load
duke
parents:
diff changeset
759 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
760 live_out.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
761 }
a61af66fc99e Initial load
duke
parents:
diff changeset
762 for (int j = 0; j < e; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
763 live_out.set_union(block->exception_handler_at(j)->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
764 }
a61af66fc99e Initial load
duke
parents:
diff changeset
765
a61af66fc99e Initial load
duke
parents:
diff changeset
766 if (!block->live_out().is_same(live_out)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
767 // A change occurred. Swap the old and new live out sets to avoid copying.
a61af66fc99e Initial load
duke
parents:
diff changeset
768 BitMap temp = block->live_out();
a61af66fc99e Initial load
duke
parents:
diff changeset
769 block->set_live_out(live_out);
a61af66fc99e Initial load
duke
parents:
diff changeset
770 live_out = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
771
a61af66fc99e Initial load
duke
parents:
diff changeset
772 change_occurred = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
773 change_occurred_in_block = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
774 }
a61af66fc99e Initial load
duke
parents:
diff changeset
775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
776
a61af66fc99e Initial load
duke
parents:
diff changeset
777 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
778 // live_in(block) is the union of live_gen(block) with (live_out(block) & !live_kill(block))
a61af66fc99e Initial load
duke
parents:
diff changeset
779 // note: live_in has to be computed only in first iteration or if live_out has changed!
a61af66fc99e Initial load
duke
parents:
diff changeset
780 BitMap live_in = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
781 live_in.set_from(block->live_out());
a61af66fc99e Initial load
duke
parents:
diff changeset
782 live_in.set_difference(block->live_kill());
a61af66fc99e Initial load
duke
parents:
diff changeset
783 live_in.set_union(block->live_gen());
a61af66fc99e Initial load
duke
parents:
diff changeset
784 }
a61af66fc99e Initial load
duke
parents:
diff changeset
785
a61af66fc99e Initial load
duke
parents:
diff changeset
786 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
787 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
788 char c = ' ';
a61af66fc99e Initial load
duke
parents:
diff changeset
789 if (iteration_count == 0 || change_occurred_in_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
790 c = '*';
a61af66fc99e Initial load
duke
parents:
diff changeset
791 }
a61af66fc99e Initial load
duke
parents:
diff changeset
792 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
793 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
794 }
a61af66fc99e Initial load
duke
parents:
diff changeset
795 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
796 }
a61af66fc99e Initial load
duke
parents:
diff changeset
797 iteration_count++;
a61af66fc99e Initial load
duke
parents:
diff changeset
798
a61af66fc99e Initial load
duke
parents:
diff changeset
799 if (change_occurred && iteration_count > 50) {
a61af66fc99e Initial load
duke
parents:
diff changeset
800 BAILOUT("too many iterations in compute_global_live_sets");
a61af66fc99e Initial load
duke
parents:
diff changeset
801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
802 } while (change_occurred);
a61af66fc99e Initial load
duke
parents:
diff changeset
803
a61af66fc99e Initial load
duke
parents:
diff changeset
804
a61af66fc99e Initial load
duke
parents:
diff changeset
805 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
806 // check that fixed intervals are not live at block boundaries
a61af66fc99e Initial load
duke
parents:
diff changeset
807 // (live set must be empty at fixed intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
808 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
809 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
810 for (int j = 0; j < LIR_OprDesc::vreg_base; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
811 assert(block->live_in().at(j) == false, "live_in set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
812 assert(block->live_out().at(j) == false, "live_out set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
813 assert(block->live_gen().at(j) == false, "live_gen set of fixed register must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
815 }
a61af66fc99e Initial load
duke
parents:
diff changeset
816 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
817
a61af66fc99e Initial load
duke
parents:
diff changeset
818 // check that the live_in set of the first block is empty
a61af66fc99e Initial load
duke
parents:
diff changeset
819 BitMap live_in_args(ir()->start()->live_in().size());
a61af66fc99e Initial load
duke
parents:
diff changeset
820 live_in_args.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
821 if (!ir()->start()->live_in().is_same(live_in_args)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
822 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
823 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
824 tty->print_cr("affected registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
825 print_bitmap(ir()->start()->live_in());
a61af66fc99e Initial load
duke
parents:
diff changeset
826
a61af66fc99e Initial load
duke
parents:
diff changeset
827 // print some additional information to simplify debugging
a61af66fc99e Initial load
duke
parents:
diff changeset
828 for (unsigned int i = 0; i < ir()->start()->live_in().size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
829 if (ir()->start()->live_in().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
830 Instruction* instr = gen()->instruction_for_vreg(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
831 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
832
a61af66fc99e Initial load
duke
parents:
diff changeset
833 for (int j = 0; j < num_blocks; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
834 BlockBegin* block = block_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
835 if (block->live_gen().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
836 tty->print_cr(" used in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
837 }
a61af66fc99e Initial load
duke
parents:
diff changeset
838 if (block->live_kill().at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
839 tty->print_cr(" defined in block B%d", block->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
840 }
a61af66fc99e Initial load
duke
parents:
diff changeset
841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
842 }
a61af66fc99e Initial load
duke
parents:
diff changeset
843 }
a61af66fc99e Initial load
duke
parents:
diff changeset
844
a61af66fc99e Initial load
duke
parents:
diff changeset
845 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
846 // when this fails, virtual registers are used before they are defined.
a61af66fc99e Initial load
duke
parents:
diff changeset
847 assert(false, "live_in set of first block must be empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
848 // bailout of if this occurs in product mode.
a61af66fc99e Initial load
duke
parents:
diff changeset
849 bailout("live_in set of first block not empty");
a61af66fc99e Initial load
duke
parents:
diff changeset
850 }
a61af66fc99e Initial load
duke
parents:
diff changeset
851 }
a61af66fc99e Initial load
duke
parents:
diff changeset
852
a61af66fc99e Initial load
duke
parents:
diff changeset
853
a61af66fc99e Initial load
duke
parents:
diff changeset
854 // ********** Phase 4: build intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
855 // (fills the list _intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
856
a61af66fc99e Initial load
duke
parents:
diff changeset
857 void LinearScan::add_use(Value value, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
858 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
859 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
860 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
861
a61af66fc99e Initial load
duke
parents:
diff changeset
862 if ((con == NULL || con->is_pinned()) && opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
863 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
864 add_use(opr, from, to, use_kind);
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 void LinearScan::add_def(LIR_Opr opr, int def_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
870 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
871 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
872
a61af66fc99e Initial load
duke
parents:
diff changeset
873 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
874 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
875 add_def(opr->vreg_number(), def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
876
a61af66fc99e Initial load
duke
parents:
diff changeset
877 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
878 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
879 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
880 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
881 }
a61af66fc99e Initial load
duke
parents:
diff changeset
882 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
883 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
884 add_def(reg, def_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
887 }
a61af66fc99e Initial load
duke
parents:
diff changeset
888
a61af66fc99e Initial load
duke
parents:
diff changeset
889 void LinearScan::add_use(LIR_Opr opr, int from, int to, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
890 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
891 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
892
a61af66fc99e Initial load
duke
parents:
diff changeset
893 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
894 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
895 add_use(opr->vreg_number(), from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
896
a61af66fc99e Initial load
duke
parents:
diff changeset
897 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
898 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
899 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
900 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
901 }
a61af66fc99e Initial load
duke
parents:
diff changeset
902 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
903 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
904 add_use(reg, from, to, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
905 }
a61af66fc99e Initial load
duke
parents:
diff changeset
906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
908
a61af66fc99e Initial load
duke
parents:
diff changeset
909 void LinearScan::add_temp(LIR_Opr opr, int temp_pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
910 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
911 assert(opr->is_register(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
912
a61af66fc99e Initial load
duke
parents:
diff changeset
913 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
914 assert(reg_num(opr) == opr->vreg_number() && !is_valid_reg_num(reg_numHi(opr)), "invalid optimization below");
a61af66fc99e Initial load
duke
parents:
diff changeset
915 add_temp(opr->vreg_number(), temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
916
a61af66fc99e Initial load
duke
parents:
diff changeset
917 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
918 int reg = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
919 if (is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
920 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
921 }
a61af66fc99e Initial load
duke
parents:
diff changeset
922 reg = reg_numHi(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
923 if (is_valid_reg_num(reg) && is_processed_reg_num(reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
924 add_temp(reg, temp_pos, use_kind, opr->type_register());
a61af66fc99e Initial load
duke
parents:
diff changeset
925 }
a61af66fc99e Initial load
duke
parents:
diff changeset
926 }
a61af66fc99e Initial load
duke
parents:
diff changeset
927 }
a61af66fc99e Initial load
duke
parents:
diff changeset
928
a61af66fc99e Initial load
duke
parents:
diff changeset
929
a61af66fc99e Initial load
duke
parents:
diff changeset
930 void LinearScan::add_def(int reg_num, int def_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
931 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
932 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
933 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
934
a61af66fc99e Initial load
duke
parents:
diff changeset
935 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
936 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
938
a61af66fc99e Initial load
duke
parents:
diff changeset
939 Range* r = interval->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
940 if (r->from() <= def_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
941 // Update the starting point (when a range is first created for a use, its
a61af66fc99e Initial load
duke
parents:
diff changeset
942 // start is the beginning of the current block until a def is encountered.)
a61af66fc99e Initial load
duke
parents:
diff changeset
943 r->set_from(def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
944 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
945
a61af66fc99e Initial load
duke
parents:
diff changeset
946 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
947 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
948 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
949 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
950 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
951 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
952 }
a61af66fc99e Initial load
duke
parents:
diff changeset
953
a61af66fc99e Initial load
duke
parents:
diff changeset
954 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
955 // Dead value - make vacuous interval
a61af66fc99e Initial load
duke
parents:
diff changeset
956 // also add use_kind for dead intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
957 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
958 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
959 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
960 }
a61af66fc99e Initial load
duke
parents:
diff changeset
961
a61af66fc99e Initial load
duke
parents:
diff changeset
962 interval->add_range(def_pos, def_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
963 interval->add_use_pos(def_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
964 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
965 }
a61af66fc99e Initial load
duke
parents:
diff changeset
966
a61af66fc99e Initial load
duke
parents:
diff changeset
967 change_spill_definition_pos(interval, def_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
968 if (use_kind == noUse && interval->spill_state() <= startInMemory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
969 // detection of method-parameters and roundfp-results
a61af66fc99e Initial load
duke
parents:
diff changeset
970 // TODO: move this directly to position where use-kind is computed
a61af66fc99e Initial load
duke
parents:
diff changeset
971 interval->set_spill_state(startInMemory);
a61af66fc99e Initial load
duke
parents:
diff changeset
972 }
a61af66fc99e Initial load
duke
parents:
diff changeset
973 }
a61af66fc99e Initial load
duke
parents:
diff changeset
974
a61af66fc99e Initial load
duke
parents:
diff changeset
975 void LinearScan::add_use(int reg_num, int from, int to, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
976 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
977 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
978 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
979 }
a61af66fc99e Initial load
duke
parents:
diff changeset
980 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
981
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(from, to);
a61af66fc99e Initial load
duke
parents:
diff changeset
987 interval->add_use_pos(to, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
988 }
a61af66fc99e Initial load
duke
parents:
diff changeset
989
a61af66fc99e Initial load
duke
parents:
diff changeset
990 void LinearScan::add_temp(int reg_num, int temp_pos, IntervalUseKind use_kind, BasicType type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
991 Interval* interval = interval_at(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
992 if (interval == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
993 interval = create_interval(reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
994 }
a61af66fc99e Initial load
duke
parents:
diff changeset
995 assert(interval->reg_num() == reg_num, "wrong interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
996
a61af66fc99e Initial load
duke
parents:
diff changeset
997 if (type != T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
998 interval->set_type(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
999 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1000
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 interval->add_range(temp_pos, temp_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 interval->add_use_pos(temp_pos, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1004
a61af66fc99e Initial load
duke
parents:
diff changeset
1005
a61af66fc99e Initial load
duke
parents:
diff changeset
1006 // the results of this functions are used for optimizing spilling and reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 // if the functions return shouldHaveRegister and the interval is spilled,
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 // it is not reloaded to a register.
a61af66fc99e Initial load
duke
parents:
diff changeset
1009 IntervalUseKind LinearScan::use_kind_of_output_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 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
1015
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 // Begin of an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 // This interval will always get a stack slot first, so return noUse.
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1020
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 } else if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 // method argument (condition must be equal to handle_method_arguments)
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1024
a61af66fc99e Initial load
duke
parents:
diff changeset
1025 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1026 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1028 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 // input operand must have a register instead of output operand (leads to better register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
1030 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1034
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 if (opr->is_virtual() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 gen()->is_vreg_flag_set(opr->vreg_number(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 // result is a stack-slot, so prevent immediate reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 return noUse;
a61af66fc99e Initial load
duke
parents:
diff changeset
1039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1040
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1044
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 IntervalUseKind LinearScan::use_kind_of_input_operand(LIR_Op* op, LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1046 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 assert(op->as_Op1() != NULL, "lir_move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1048 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 LIR_Opr res = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 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
1051
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 if (result_in_memory) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 // Move to an interval with must_start_in_memory set.
a61af66fc99e Initial load
duke
parents:
diff changeset
1054 // To avoid moves from stack to stack (not allowed) force the input operand to a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1056
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 } else if (move->in_opr()->is_register() && move->result_opr()->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1058 // Move from register to register
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 if (block_of_op_with_id(op->id())->is_set(BlockBegin::osr_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1060 // special handling of phi-function moves inside osr-entry blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 // input operand must have a register instead of output operand (leads to better register allocation)
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1064
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 // The input operand is not forced to a register (moves from stack to register are allowed),
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 // but it is faster if the input operand is in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1070
a61af66fc99e Initial load
duke
parents:
diff changeset
1071
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1072 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 if (op->code() == lir_cmove) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 // conditional moves can handle stack operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1075 assert(op->result_opr()->is_register(), "result must always be in a register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1078
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 // optimizations for second input operand of arithmehtic operations on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 // this operand is allowed to be on the stack in some cases
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 BasicType opr_type = opr->type_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 if (opr_type == T_FLOAT || opr_type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 if ((UseSSE == 1 && opr_type == T_FLOAT) || UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 // SSE float instruction (T_DOUBLE only supported with SSE2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1087 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1088 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 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
1096 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1100 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 // FPU stack float instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 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
1112 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1117
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 } else if (opr_type != T_LONG) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 // integer instruction (note: long operands must always be in register)
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 case lir_cmp:
a61af66fc99e Initial load
duke
parents:
diff changeset
1122 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
1124 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
1125 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 {
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 assert(op->as_Op2() != NULL, "must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 LIR_Op2* op2 = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 if (op2->in_opr1() != op2->in_opr2() && op2->in_opr2() == opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 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
1132 return shouldHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1137 #endif // X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1138
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 // all other operands require a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 return mustHaveRegister;
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1142
a61af66fc99e Initial load
duke
parents:
diff changeset
1143
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 void LinearScan::handle_method_arguments(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 // special handling for method arguments (moves from stack to virtual register):
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 // the interval gets no register assigned, but the stack slot.
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 // it is split before the first use by the register allocator.
a61af66fc99e Initial load
duke
parents:
diff changeset
1148
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1152
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 if (move->in_opr()->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 int arg_size = compilation()->method()->arg_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 LIR_Opr o = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 if (o->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 assert(o->single_stack_ix() >= 0 && o->single_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1159 } else if (o->is_double_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 assert(o->double_stack_ix() >= 0 && o->double_stack_ix() < arg_size, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1164
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 assert(move->id() > 0, "invalid id");
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 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
1167 assert(move->result_opr()->is_virtual(), "result of move must be a virtual register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1168
a61af66fc99e Initial load
duke
parents:
diff changeset
1169 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
1170 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1171
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 Interval* interval = interval_at(reg_num(move->result_opr()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1173
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 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
1175 interval->set_canonical_spill_slot(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1176 interval->assign_reg(stack_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1180
a61af66fc99e Initial load
duke
parents:
diff changeset
1181 void LinearScan::handle_doubleword_moves(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 // special handling for doubleword move from memory to register:
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 // in this case the registers of the input address and the result
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 // registers must not overlap -> add a temp range for the input registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 assert(op->as_Op1() != NULL, "must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1188
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 if (move->result_opr()->is_double_cpu() && move->in_opr()->is_pointer()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1190 LIR_Address* address = move->in_opr()->as_address_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 if (address != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 if (address->base()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 add_temp(address->base(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 if (address->index()->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 add_temp(address->index(), op->id(), noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1202
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 void LinearScan::add_register_hints(LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 case lir_move: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 case lir_convert: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 assert(op->as_Op1() != NULL, "lir_move, lir_convert must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1209
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 LIR_Opr move_from = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 LIR_Opr move_to = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1212
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1215 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 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
1219 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 case lir_cmove: {
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 assert(op->as_Op2() != NULL, "lir_cmove must be LIR_Op2");
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 LIR_Op2* cmove = (LIR_Op2*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
1226
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 LIR_Opr move_from = cmove->in_opr1();
a61af66fc99e Initial load
duke
parents:
diff changeset
1228 LIR_Opr move_to = cmove->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1229
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 if (move_to->is_register() && move_from->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 Interval* from = interval_at(reg_num(move_from));
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 Interval* to = interval_at(reg_num(move_to));
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 if (from != NULL && to != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 to->set_register_hint(from);
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 TRACE_LINEAR_SCAN(4, tty->print_cr("operation at op_id %d: added hint from interval %d to %d", cmove->id(), from->reg_num(), to->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1242
a61af66fc99e Initial load
duke
parents:
diff changeset
1243
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 void LinearScan::build_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 TIME_LINEAR_SCAN(timer_build_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1246
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 // initialize interval list with expected number of intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 // (32 is added to have some space for split children without having to resize the list)
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 _intervals = IntervalList(num_virtual_regs() + 32);
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 // initialize all slots that are used by build_intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 _intervals.at_put_grow(num_virtual_regs() - 1, NULL, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1252
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 // create a list with all caller-save registers (cpu, fpu, xmm)
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 // when an instruction is a call, a temp range is created for all these registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1255 int num_caller_save_registers = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 int caller_save_registers[LinearScan::nof_regs];
a61af66fc99e Initial load
duke
parents:
diff changeset
1257
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1259 for (i = 0; i < FrameMap::nof_caller_save_cpu_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 LIR_Opr opr = FrameMap::caller_save_cpu_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1261 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1265
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 // temp ranges for fpu registers are only created when the method has
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 // virtual fpu operands. Otherwise no allocation for fpu registers is
a61af66fc99e Initial load
duke
parents:
diff changeset
1268 // perfomed and so the temp ranges would be useless
a61af66fc99e Initial load
duke
parents:
diff changeset
1269 if (has_fpu_registers()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1270 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1271 if (UseSSE < 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1273 for (i = 0; i < FrameMap::nof_caller_save_fpu_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1274 LIR_Opr opr = FrameMap::caller_save_fpu_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1277 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1279 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 if (UseSSE > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1282 for (i = 0; i < FrameMap::nof_caller_save_xmm_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1283 LIR_Opr opr = FrameMap::caller_save_xmm_reg_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 assert(opr->is_valid() && opr->is_register(), "FrameMap should not return invalid operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1285 assert(reg_numHi(opr) == -1, "missing addition of range for hi-register");
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 caller_save_registers[num_caller_save_registers++] = reg_num(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1291 assert(num_caller_save_registers <= LinearScan::nof_regs, "out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1292
a61af66fc99e Initial load
duke
parents:
diff changeset
1293
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1295
a61af66fc99e Initial load
duke
parents:
diff changeset
1296 // iterate all blocks in reverse order
a61af66fc99e Initial load
duke
parents:
diff changeset
1297 for (i = block_count() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 int block_from = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1301 int block_to = block->last_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1302
a61af66fc99e Initial load
duke
parents:
diff changeset
1303 assert(block_from == instructions->at(0)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 assert(block_to == instructions->at(instructions->length() - 1)->id(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
1305
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 // Update intervals for registers live at the end of this block;
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 BitMap live = block->live_out();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1308 int size = (int)live.size();
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1309 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
1310 assert(live.at(number), "should not stop here otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 assert(number >= LIR_OprDesc::vreg_base, "fixed intervals must not be live on block bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1312 TRACE_LINEAR_SCAN(2, tty->print_cr("live in %d to %d", number, block_to + 2));
a61af66fc99e Initial load
duke
parents:
diff changeset
1313
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 add_use(number, block_from, block_to + 2, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1315
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 // add special use positions for loop-end blocks when the
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 // interval is used anywhere inside this loop. It's possible
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 // that the block was part of a non-natural loop, so it might
a61af66fc99e Initial load
duke
parents:
diff changeset
1319 // have an invalid loop index.
a61af66fc99e Initial load
duke
parents:
diff changeset
1320 if (block->is_set(BlockBegin::linear_scan_loop_end_flag) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1321 block->loop_index() != -1 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 is_interval_in_loop(number, block->loop_index())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 interval_at(number)->add_use_pos(block_to + 1, loopEndMarker);
a61af66fc99e Initial load
duke
parents:
diff changeset
1324 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1325 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1326
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 // iterate all instructions of the block in reverse order.
a61af66fc99e Initial load
duke
parents:
diff changeset
1328 // skip the first instruction because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 // definitions of intervals are processed before uses
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 assert(visitor.no_operands(instructions->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1331 for (int j = instructions->length() - 1; j >= 1; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1332 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1334
a61af66fc99e Initial load
duke
parents:
diff changeset
1335 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1337
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 // add a temp range for each register if operation destroys caller-save registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1339 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 for (int k = 0; k < num_caller_save_registers; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1341 add_temp(caller_save_registers[k], op_id, noUse, T_ILLEGAL);
a61af66fc99e Initial load
duke
parents:
diff changeset
1342 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 TRACE_LINEAR_SCAN(4, tty->print_cr("operation destroys all caller-save registers"));
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1345
a61af66fc99e Initial load
duke
parents:
diff changeset
1346 // Add any platform dependent temps
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 pd_add_temps(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1348
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 // visit definitions (output and temp operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 int k, n;
a61af66fc99e Initial load
duke
parents:
diff changeset
1351 n = visitor.opr_count(LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1352 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::outputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1354 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1355 add_def(opr, op_id, use_kind_of_output_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1357
a61af66fc99e Initial load
duke
parents:
diff changeset
1358 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1362 add_temp(opr, op_id, mustHaveRegister);
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1364
a61af66fc99e Initial load
duke
parents:
diff changeset
1365 // visit uses (input operands)
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1368 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1369 assert(opr->is_register(), "visitor should only return register operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1370 add_use(opr, block_from, op_id, use_kind_of_input_operand(op, opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
1371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1372
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 // Add uses of live locals from interpreter's point of view for proper
a61af66fc99e Initial load
duke
parents:
diff changeset
1374 // debug information generation
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 // Treat these operands as temp values (if the life range is extended
a61af66fc99e Initial load
duke
parents:
diff changeset
1376 // to a call site, the value would be in a register at the call otherwise)
a61af66fc99e Initial load
duke
parents:
diff changeset
1377 n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1378 for (k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1379 CodeEmitInfo* info = visitor.info_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1380 ValueStack* stack = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
1381 for_each_state_value(stack, value,
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 add_use(value, block_from, op_id + 1, noUse);
a61af66fc99e Initial load
duke
parents:
diff changeset
1383 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1385
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 // special steps for some instructions (especially moves)
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 handle_method_arguments(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1388 handle_doubleword_moves(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1389 add_register_hints(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1390
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 } // end of instruction iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 } // end of block iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1393
a61af66fc99e Initial load
duke
parents:
diff changeset
1394
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 // add the range [0, 1[ to all fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1396 // -> the register allocator need not handle unhandled fixed intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1397 for (int n = 0; n < LinearScan::nof_regs; n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1398 Interval* interval = interval_at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
1399 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1400 interval->add_range(0, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1401 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1402 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1403 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1404
a61af66fc99e Initial load
duke
parents:
diff changeset
1405
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 // ********** Phase 5: actual register allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
1407
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 int LinearScan::interval_cmp(Interval** a, Interval** b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1409 if (*a != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1410 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1411 return (*a)->from() - (*b)->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1413 return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1414 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1415 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1416 if (*b != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1417 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1418 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1419 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1421 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1422 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1423
a61af66fc99e Initial load
duke
parents:
diff changeset
1424 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 bool LinearScan::is_sorted(IntervalArray* intervals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1426 int from = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1428 for (i = 0; i < intervals->length(); i ++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1429 Interval* it = intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1430 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1431 if (from > it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 assert(false, "");
a61af66fc99e Initial load
duke
parents:
diff changeset
1433 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 from = it->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1438
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 // check in both directions if sorted list and unsorted list contain same intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1440 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 if (interval_at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1442 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1447 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1449 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1451 for (j = 0; j < intervals->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1452 int num_found = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1453 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1454 if (interval_at(i) == intervals->at(j)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1455 num_found++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 assert(num_found == 1, "lists do not contain same intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1460
a61af66fc99e Initial load
duke
parents:
diff changeset
1461 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1462 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1464
a61af66fc99e Initial load
duke
parents:
diff changeset
1465 void LinearScan::add_to_list(Interval** first, Interval** prev, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 if (*prev != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 (*prev)->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 *first = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 *prev = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1473
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 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
1475 assert(is_sorted(_sorted_intervals), "interval list is not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
1476
a61af66fc99e Initial load
duke
parents:
diff changeset
1477 *list1 = *list2 = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
1478
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 Interval* list1_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1480 Interval* list2_prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1481 Interval* v;
a61af66fc99e Initial load
duke
parents:
diff changeset
1482
a61af66fc99e Initial load
duke
parents:
diff changeset
1483 const int n = _sorted_intervals->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1484 for (int i = 0; i < n; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 v = _sorted_intervals->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1486 if (v == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
1487
a61af66fc99e Initial load
duke
parents:
diff changeset
1488 if (is_list1(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 add_to_list(list1, &list1_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1490 } else if (is_list2 == NULL || is_list2(v)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1491 add_to_list(list2, &list2_prev, v);
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1493 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1494
a61af66fc99e Initial load
duke
parents:
diff changeset
1495 if (list1_prev != NULL) list1_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 if (list2_prev != NULL) list2_prev->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
1497
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 assert(list1_prev == NULL || list1_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1499 assert(list2_prev == NULL || list2_prev->next() == Interval::end(), "linear list ends not with sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1500 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1501
a61af66fc99e Initial load
duke
parents:
diff changeset
1502
a61af66fc99e Initial load
duke
parents:
diff changeset
1503 void LinearScan::sort_intervals_before_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1504 TIME_LINEAR_SCAN(timer_sort_intervals_before);
a61af66fc99e Initial load
duke
parents:
diff changeset
1505
a61af66fc99e Initial load
duke
parents:
diff changeset
1506 IntervalList* unsorted_list = &_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 int unsorted_len = unsorted_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1508 int sorted_len = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1509 int unsorted_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
1510 int sorted_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1511 int sorted_from_max = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1512
a61af66fc99e Initial load
duke
parents:
diff changeset
1513 // calc number of items for sorted list (sorted list must not contain NULL values)
a61af66fc99e Initial load
duke
parents:
diff changeset
1514 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 if (unsorted_list->at(unsorted_idx) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 sorted_len++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1518 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1519 IntervalArray* sorted_list = new IntervalArray(sorted_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1520
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 // special sorting algorithm: the original interval-list is almost sorted,
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 // only some intervals are swapped. So this is much faster than a complete QuickSort
a61af66fc99e Initial load
duke
parents:
diff changeset
1523 for (unsorted_idx = 0; unsorted_idx < unsorted_len; unsorted_idx++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1524 Interval* cur_interval = unsorted_list->at(unsorted_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
1525
a61af66fc99e Initial load
duke
parents:
diff changeset
1526 if (cur_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1527 int cur_from = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1528
a61af66fc99e Initial load
duke
parents:
diff changeset
1529 if (sorted_from_max <= cur_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1530 sorted_list->at_put(sorted_idx++, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1531 sorted_from_max = cur_interval->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
1532 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1533 // the asumption that the intervals are already sorted failed,
a61af66fc99e Initial load
duke
parents:
diff changeset
1534 // so this interval must be sorted in manually
a61af66fc99e Initial load
duke
parents:
diff changeset
1535 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
1536 for (j = sorted_idx - 1; j >= 0 && cur_from < sorted_list->at(j)->from(); j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1537 sorted_list->at_put(j + 1, sorted_list->at(j));
a61af66fc99e Initial load
duke
parents:
diff changeset
1538 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1539 sorted_list->at_put(j + 1, cur_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 sorted_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1542 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1544 _sorted_intervals = sorted_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1546
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 void LinearScan::sort_intervals_after_allocation() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1548 TIME_LINEAR_SCAN(timer_sort_intervals_after);
a61af66fc99e Initial load
duke
parents:
diff changeset
1549
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 IntervalArray* old_list = _sorted_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1551 IntervalList* new_list = _new_intervals_from_allocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
1552 int old_len = old_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 int new_len = new_list->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1554
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 if (new_len == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1556 // no intervals have been added during allocation, so sorted list is already up to date
a61af66fc99e Initial load
duke
parents:
diff changeset
1557 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1558 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1559
a61af66fc99e Initial load
duke
parents:
diff changeset
1560 // conventional sort-algorithm for new intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 new_list->sort(interval_cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1562
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 // merge old and new list (both already sorted) into one combined list
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 IntervalArray* combined_list = new IntervalArray(old_len + new_len);
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 int old_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1566 int new_idx = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1567
a61af66fc99e Initial load
duke
parents:
diff changeset
1568 while (old_idx + new_idx < old_len + new_len) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 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
1570 combined_list->at_put(old_idx + new_idx, old_list->at(old_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1571 old_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
1572 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1573 combined_list->at_put(old_idx + new_idx, new_list->at(new_idx));
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 new_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 = combined_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
1579 }
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::allocate_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1583 TIME_LINEAR_SCAN(timer_allocate_registers);
a61af66fc99e Initial load
duke
parents:
diff changeset
1584
a61af66fc99e Initial load
duke
parents:
diff changeset
1585 Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1586 Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
1587
a61af66fc99e Initial load
duke
parents:
diff changeset
1588 create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1589 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1591 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1592 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1593 // fpu register allocation is omitted because no virtual fpu registers are present
a61af66fc99e Initial load
duke
parents:
diff changeset
1594 // just check this again...
a61af66fc99e Initial load
duke
parents:
diff changeset
1595 create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1596 assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1597 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1598 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1599
a61af66fc99e Initial load
duke
parents:
diff changeset
1600 // allocate cpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1601 LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1602 cpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 cpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1604
a61af66fc99e Initial load
duke
parents:
diff changeset
1605 if (has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1606 // allocate fpu registers
a61af66fc99e Initial load
duke
parents:
diff changeset
1607 LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 fpu_lsw.walk();
a61af66fc99e Initial load
duke
parents:
diff changeset
1609 fpu_lsw.finish_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
1610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1612
a61af66fc99e Initial load
duke
parents:
diff changeset
1613
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 // ********** Phase 6: resolve data flow
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 // (insert moves at edges between blocks if intervals have been split)
a61af66fc99e Initial load
duke
parents:
diff changeset
1616
a61af66fc99e Initial load
duke
parents:
diff changeset
1617 // wrapper for Interval::split_child_at_op_id that performs a bailout in product mode
a61af66fc99e Initial load
duke
parents:
diff changeset
1618 // instead of returning NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
1619 Interval* LinearScan::split_child_at_op_id(Interval* interval, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1620 Interval* result = interval->split_child_at_op_id(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1621 if (result != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1622 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
1623 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1624
a61af66fc99e Initial load
duke
parents:
diff changeset
1625 assert(false, "must find an interval, but do a clean bailout in product mode");
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 result = new Interval(LIR_OprDesc::vreg_base);
a61af66fc99e Initial load
duke
parents:
diff changeset
1627 result->assign_reg(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1628 result->set_type(T_INT);
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 BAILOUT_("LinearScan: interval is NULL", result);
a61af66fc99e Initial load
duke
parents:
diff changeset
1630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1631
a61af66fc99e Initial load
duke
parents:
diff changeset
1632
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 Interval* LinearScan::interval_at_block_begin(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1634 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1635 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1636
a61af66fc99e Initial load
duke
parents:
diff changeset
1637 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
1638 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1639
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 Interval* LinearScan::interval_at_block_end(BlockBegin* block, int reg_num) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1643
a61af66fc99e Initial load
duke
parents:
diff changeset
1644 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
1645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1646
a61af66fc99e Initial load
duke
parents:
diff changeset
1647 Interval* LinearScan::interval_at_op_id(int reg_num, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1648 assert(LinearScan::nof_regs <= reg_num && reg_num < num_virtual_regs(), "register number out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 assert(interval_at(reg_num) != NULL, "no interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
1650
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 return split_child_at_op_id(interval_at(reg_num), op_id, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1653
a61af66fc99e Initial load
duke
parents:
diff changeset
1654
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 void LinearScan::resolve_collect_mappings(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1656 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1657
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 const int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
1659 const int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1660 const BitMap live_at_edge = to_block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
1661
a61af66fc99e Initial load
duke
parents:
diff changeset
1662 // 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
1663 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
1664 assert(r < num_regs, "live information set for not exisiting interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 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
1666
a61af66fc99e Initial load
duke
parents:
diff changeset
1667 Interval* from_interval = interval_at_block_end(from_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 Interval* to_interval = interval_at_block_begin(to_block, r);
a61af66fc99e Initial load
duke
parents:
diff changeset
1669
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 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
1671 // need to insert move instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1672 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1674 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1676
a61af66fc99e Initial load
duke
parents:
diff changeset
1677
a61af66fc99e Initial load
duke
parents:
diff changeset
1678 void LinearScan::resolve_find_insert_pos(BlockBegin* from_block, BlockBegin* to_block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1679 if (from_block->number_of_sux() <= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1680 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
1681
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 LIR_OpList* instructions = from_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1683 LIR_OpBranch* branch = instructions->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 // insert moves before branch
a61af66fc99e Initial load
duke
parents:
diff changeset
1686 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
1687 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1688 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1689 move_resolver.set_insert_position(from_block->lir(), instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1691
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1693 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
1694 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1695 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
1696
a61af66fc99e Initial load
duke
parents:
diff changeset
1697 // because the number of predecessor edges matches the number of
a61af66fc99e Initial load
duke
parents:
diff changeset
1698 // successor edges, blocks which are reached by switch statements
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 // may have be more than one predecessor but it will be guaranteed
a61af66fc99e Initial load
duke
parents:
diff changeset
1700 // that all predecessors will be the same.
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 for (int i = 0; i < to_block->number_of_preds(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 assert(from_block == to_block->pred_at(i), "all critical edges must be broken");
a61af66fc99e Initial load
duke
parents:
diff changeset
1703 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1704 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1705
a61af66fc99e Initial load
duke
parents:
diff changeset
1706 move_resolver.set_insert_position(to_block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1707 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1708 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1709
a61af66fc99e Initial load
duke
parents:
diff changeset
1710
a61af66fc99e Initial load
duke
parents:
diff changeset
1711 // insert necessary moves (spilling or reloading) at edges between blocks if interval has been split
a61af66fc99e Initial load
duke
parents:
diff changeset
1712 void LinearScan::resolve_data_flow() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1713 TIME_LINEAR_SCAN(timer_resolve_data_flow);
a61af66fc99e Initial load
duke
parents:
diff changeset
1714
a61af66fc99e Initial load
duke
parents:
diff changeset
1715 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1716 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1717 BitMap block_completed(num_blocks); block_completed.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1718 BitMap already_resolved(num_blocks); already_resolved.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
1719
a61af66fc99e Initial load
duke
parents:
diff changeset
1720 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1721 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1722 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1723
a61af66fc99e Initial load
duke
parents:
diff changeset
1724 // check if block has only one predecessor and only one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 if (block->number_of_preds() == 1 && block->number_of_sux() == 1 && block->number_of_exception_handlers() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1726 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
1727 assert(instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1728 assert(instructions->last()->code() == lir_branch, "block with successors must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1729 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block with successor must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
1730
a61af66fc99e Initial load
duke
parents:
diff changeset
1731 // check if block is empty (only label and branch)
a61af66fc99e Initial load
duke
parents:
diff changeset
1732 if (instructions->length() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1733 BlockBegin* pred = block->pred_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1734 BlockBegin* sux = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1735
a61af66fc99e Initial load
duke
parents:
diff changeset
1736 // prevent optimization of two consecutive blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
1737 if (!block_completed.at(pred->linear_scan_number()) && !block_completed.at(sux->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1738 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
1739 block_completed.set_bit(block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1740
a61af66fc99e Initial load
duke
parents:
diff changeset
1741 // directly resolve between pred and sux (without looking at the empty block between)
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 resolve_collect_mappings(pred, sux, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1743 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 move_resolver.set_insert_position(block->lir(), 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1745 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1746 }
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
a61af66fc99e Initial load
duke
parents:
diff changeset
1752
a61af66fc99e Initial load
duke
parents:
diff changeset
1753 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1754 if (!block_completed.at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1755 BlockBegin* from_block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1756 already_resolved.set_from(block_completed);
a61af66fc99e Initial load
duke
parents:
diff changeset
1757
a61af66fc99e Initial load
duke
parents:
diff changeset
1758 int num_sux = from_block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
1759 for (int s = 0; s < num_sux; s++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1760 BlockBegin* to_block = from_block->sux_at(s);
a61af66fc99e Initial load
duke
parents:
diff changeset
1761
a61af66fc99e Initial load
duke
parents:
diff changeset
1762 // check for duplicate edges between the same blocks (can happen with switch blocks)
a61af66fc99e Initial load
duke
parents:
diff changeset
1763 if (!already_resolved.at(to_block->linear_scan_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1764 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
1765 already_resolved.set_bit(to_block->linear_scan_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
1766
a61af66fc99e Initial load
duke
parents:
diff changeset
1767 // collect all intervals that have been split between from_block and to_block
a61af66fc99e Initial load
duke
parents:
diff changeset
1768 resolve_collect_mappings(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1769 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1770 resolve_find_insert_pos(from_block, to_block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1771 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1772 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1773 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1774 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1776 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1777 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1778
a61af66fc99e Initial load
duke
parents:
diff changeset
1779
a61af66fc99e Initial load
duke
parents:
diff changeset
1780 void LinearScan::resolve_exception_entry(BlockBegin* block, int reg_num, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1781 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1782 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1783 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1784 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1785
a61af66fc99e Initial load
duke
parents:
diff changeset
1786 Interval* interval = interval_at_block_begin(block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1787 int reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1788 int regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
1789
a61af66fc99e Initial load
duke
parents:
diff changeset
1790 if ((reg < nof_regs && interval->always_in_memory()) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1791 (use_fpu_stack_allocation() && reg >= pd_first_fpu_reg && reg <= pd_last_fpu_reg)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1792 // the interval is split to get a short range that is located on the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
1793 // in the following two cases:
a61af66fc99e Initial load
duke
parents:
diff changeset
1794 // * the interval started in memory (e.g. method parameter), but is currently in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
1795 // this is an optimization for exception handling that reduces the number of moves that
a61af66fc99e Initial load
duke
parents:
diff changeset
1796 // are necessary for resolving the states when an exception uses this exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1797 // * the interval would be on the fpu stack at the begin of the exception handler
a61af66fc99e Initial load
duke
parents:
diff changeset
1798 // this is not allowed because of the complicated fpu stack handling on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
1799
a61af66fc99e Initial load
duke
parents:
diff changeset
1800 // range that will be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
1801 int from_op_id = block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1802 int to_op_id = from_op_id + 1; // short live range of length 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1803 assert(interval->from() <= from_op_id && interval->to() >= to_op_id,
a61af66fc99e Initial load
duke
parents:
diff changeset
1804 "no split allowed between exception entry and first instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
1805
a61af66fc99e Initial load
duke
parents:
diff changeset
1806 if (interval->from() != from_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1807 // the part before from_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1808 interval = interval->split(from_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1809 interval->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
1810 append_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1811 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1812 assert(interval->from() == from_op_id, "must be true now");
a61af66fc99e Initial load
duke
parents:
diff changeset
1813
a61af66fc99e Initial load
duke
parents:
diff changeset
1814 Interval* spilled_part = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
1815 if (interval->to() != to_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1816 // the part after to_op_id is unchanged
a61af66fc99e Initial load
duke
parents:
diff changeset
1817 spilled_part = interval->split_from_start(to_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1818 append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1819 move_resolver.add_mapping(spilled_part, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1820 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1821 assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
1822
a61af66fc99e Initial load
duke
parents:
diff changeset
1823 assert(spilled_part->from() == from_op_id && spilled_part->to() == to_op_id, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
1824 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1825 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1826
a61af66fc99e Initial load
duke
parents:
diff changeset
1827 void LinearScan::resolve_exception_entry(BlockBegin* block, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1828 assert(block->is_set(BlockBegin::exception_entry_flag), "should not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1829 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1830
a61af66fc99e Initial load
duke
parents:
diff changeset
1831 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1832 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1833 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
1834 resolve_exception_entry(block, r, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1835 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1836
a61af66fc99e Initial load
duke
parents:
diff changeset
1837 // 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
1838 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1839 resolve_exception_entry(block, phi->operand()->vreg_number(), move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1840 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1841
a61af66fc99e Initial load
duke
parents:
diff changeset
1842 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1843 // insert moves after first instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
1844 move_resolver.set_insert_position(block->lir(), 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1845 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1846 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1847 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1848
a61af66fc99e Initial load
duke
parents:
diff changeset
1849
a61af66fc99e Initial load
duke
parents:
diff changeset
1850 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
1851 if (interval_at(reg_num) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1852 // if a phi function is never used, no interval is created -> ignore this
a61af66fc99e Initial load
duke
parents:
diff changeset
1853 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1854 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1855
a61af66fc99e Initial load
duke
parents:
diff changeset
1856 // the computation of to_interval is equal to resolve_collect_mappings,
a61af66fc99e Initial load
duke
parents:
diff changeset
1857 // but from_interval is more complicated because of phi functions
a61af66fc99e Initial load
duke
parents:
diff changeset
1858 BlockBegin* to_block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1859 Interval* to_interval = interval_at_block_begin(to_block, reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
1860
a61af66fc99e Initial load
duke
parents:
diff changeset
1861 if (phi != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1862 // phi function of the exception entry block
a61af66fc99e Initial load
duke
parents:
diff changeset
1863 // no moves are created for this phi function in the LIR_Generator, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
1864 // interval at the throwing instruction must be searched using the operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1865 // of the phi function
a61af66fc99e Initial load
duke
parents:
diff changeset
1866 Value from_value = phi->operand_at(handler->phi_operand());
a61af66fc99e Initial load
duke
parents:
diff changeset
1867
a61af66fc99e Initial load
duke
parents:
diff changeset
1868 // with phi functions it can happen that the same from_value is used in
a61af66fc99e Initial load
duke
parents:
diff changeset
1869 // multiple mappings, so notify move-resolver that this is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
1870 move_resolver.set_multiple_reads_allowed();
a61af66fc99e Initial load
duke
parents:
diff changeset
1871
a61af66fc99e Initial load
duke
parents:
diff changeset
1872 Constant* con = from_value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
1873 if (con != NULL && !con->is_pinned()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1874 // unpinned constants may have no register, so add mapping from constant to interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1875 move_resolver.add_mapping(LIR_OprFact::value_type(con->type()), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1876 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1877 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1878 Interval* from_interval = interval_at_op_id(from_value->operand()->vreg_number(), throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1879 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1880 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1881
a61af66fc99e Initial load
duke
parents:
diff changeset
1882 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1883 // no phi function, so use reg_num also for from_interval
a61af66fc99e Initial load
duke
parents:
diff changeset
1884 // search split child at the throwing op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
1885 Interval* from_interval = interval_at_op_id(reg_num, throwing_op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
1886 if (from_interval != to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1887 // optimization to reduce number of moves: when to_interval is on stack and
a61af66fc99e Initial load
duke
parents:
diff changeset
1888 // the stack slot is known to be always correct, then no move is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
1889 if (!from_interval->always_in_memory() || from_interval->canonical_spill_slot() != to_interval->assigned_reg()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1890 move_resolver.add_mapping(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1891 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1892 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1893 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1894 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1895
a61af66fc99e Initial load
duke
parents:
diff changeset
1896 void LinearScan::resolve_exception_edge(XHandler* handler, int throwing_op_id, MoveResolver &move_resolver) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1897 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
1898
a61af66fc99e Initial load
duke
parents:
diff changeset
1899 DEBUG_ONLY(move_resolver.check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
1900 assert(handler->lir_op_id() == -1, "already processed this xhandler");
a61af66fc99e Initial load
duke
parents:
diff changeset
1901 DEBUG_ONLY(handler->set_lir_op_id(throwing_op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
1902 assert(handler->entry_code() == NULL, "code already present");
a61af66fc99e Initial load
duke
parents:
diff changeset
1903
a61af66fc99e Initial load
duke
parents:
diff changeset
1904 // visit all registers where the live_in bit is set
a61af66fc99e Initial load
duke
parents:
diff changeset
1905 BlockBegin* block = handler->entry_block();
a61af66fc99e Initial load
duke
parents:
diff changeset
1906 int size = live_set_size();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
1907 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
1908 resolve_exception_edge(handler, throwing_op_id, r, NULL, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1909 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1910
a61af66fc99e Initial load
duke
parents:
diff changeset
1911 // 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
1912 for_each_phi_fun(block, phi,
a61af66fc99e Initial load
duke
parents:
diff changeset
1913 resolve_exception_edge(handler, throwing_op_id, phi->operand()->vreg_number(), phi, move_resolver)
a61af66fc99e Initial load
duke
parents:
diff changeset
1914 );
a61af66fc99e Initial load
duke
parents:
diff changeset
1915
a61af66fc99e Initial load
duke
parents:
diff changeset
1916 if (move_resolver.has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1917 LIR_List* entry_code = new LIR_List(compilation());
a61af66fc99e Initial load
duke
parents:
diff changeset
1918 move_resolver.set_insert_position(entry_code, 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1919 move_resolver.resolve_and_append_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
1920
a61af66fc99e Initial load
duke
parents:
diff changeset
1921 entry_code->jump(handler->entry_block());
a61af66fc99e Initial load
duke
parents:
diff changeset
1922 handler->set_entry_code(entry_code);
a61af66fc99e Initial load
duke
parents:
diff changeset
1923 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1924 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1925
a61af66fc99e Initial load
duke
parents:
diff changeset
1926
a61af66fc99e Initial load
duke
parents:
diff changeset
1927 void LinearScan::resolve_exception_handlers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1928 MoveResolver move_resolver(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
1929 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
1930 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
1931
a61af66fc99e Initial load
duke
parents:
diff changeset
1932 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1933 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1934 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1935 if (block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1936 resolve_exception_entry(block, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1939
a61af66fc99e Initial load
duke
parents:
diff changeset
1940 for (i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1941 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1942 LIR_List* ops = block->lir();
a61af66fc99e Initial load
duke
parents:
diff changeset
1943 int num_ops = ops->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1944
a61af66fc99e Initial load
duke
parents:
diff changeset
1945 // iterate all instructions of the block. skip the first because it is always a label
a61af66fc99e Initial load
duke
parents:
diff changeset
1946 assert(visitor.no_operands(ops->at(0)), "first operation must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
1947 for (int j = 1; j < num_ops; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1948 LIR_Op* op = ops->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
1949 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
1950
a61af66fc99e Initial load
duke
parents:
diff changeset
1951 if (op_id != -1 && has_info(op_id)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1952 // visit operation to collect all operands
a61af66fc99e Initial load
duke
parents:
diff changeset
1953 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1954 assert(visitor.info_count() > 0, "should not visit otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
1955
a61af66fc99e Initial load
duke
parents:
diff changeset
1956 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
1957 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
1958 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1959 resolve_exception_edge(xhandlers->handler_at(k), op_id, move_resolver);
a61af66fc99e Initial load
duke
parents:
diff changeset
1960 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1961
a61af66fc99e Initial load
duke
parents:
diff changeset
1962 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1963 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1964 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
1965 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
1966 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1968 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1969 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1970 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1971
a61af66fc99e Initial load
duke
parents:
diff changeset
1972
a61af66fc99e Initial load
duke
parents:
diff changeset
1973 // ********** Phase 7: assign register numbers back to LIR
a61af66fc99e Initial load
duke
parents:
diff changeset
1974 // (includes computation of debug information and oop maps)
a61af66fc99e Initial load
duke
parents:
diff changeset
1975
a61af66fc99e Initial load
duke
parents:
diff changeset
1976 VMReg LinearScan::vm_reg_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1977 VMReg reg = interval->cached_vm_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
1978 if (!reg->is_valid() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1979 reg = vm_reg_for_operand(operand_for_interval(interval));
a61af66fc99e Initial load
duke
parents:
diff changeset
1980 interval->set_cached_vm_reg(reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
1981 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1982 assert(reg == vm_reg_for_operand(operand_for_interval(interval)), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
1983 return reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
1984 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1985
a61af66fc99e Initial load
duke
parents:
diff changeset
1986 VMReg LinearScan::vm_reg_for_operand(LIR_Opr opr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1987 assert(opr->is_oop(), "currently only implemented for oop operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
1988 return frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1989 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1990
a61af66fc99e Initial load
duke
parents:
diff changeset
1991
a61af66fc99e Initial load
duke
parents:
diff changeset
1992 LIR_Opr LinearScan::operand_for_interval(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1993 LIR_Opr opr = interval->cached_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
1994 if (opr->is_illegal()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1995 opr = calc_operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
1996 interval->set_cached_opr(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
1997 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1998
a61af66fc99e Initial load
duke
parents:
diff changeset
1999 assert(opr == calc_operand_for_interval(interval), "wrong cached value");
a61af66fc99e Initial load
duke
parents:
diff changeset
2000 return opr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2001 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2002
a61af66fc99e Initial load
duke
parents:
diff changeset
2003 LIR_Opr LinearScan::calc_operand_for_interval(const Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2004 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2005 BasicType type = interval->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2006
a61af66fc99e Initial load
duke
parents:
diff changeset
2007 if (assigned_reg >= nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2008 // stack slot
a61af66fc99e Initial load
duke
parents:
diff changeset
2009 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2010 return LIR_OprFact::stack(assigned_reg - nof_regs, type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2011
a61af66fc99e Initial load
duke
parents:
diff changeset
2012 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2013 // register
a61af66fc99e Initial load
duke
parents:
diff changeset
2014 switch (type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2015 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2016 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2017 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2018 return LIR_OprFact::single_cpu_oop(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2020
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2021 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2022 case T_FLOAT: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2023 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2024 case T_INT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2025 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2026 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2027 return LIR_OprFact::single_cpu(assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2028 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2029
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2030 #ifdef __SOFTFP__
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2031 case T_DOUBLE: // fall through
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2032 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2033 case T_LONG: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2034 int assigned_regHi = interval->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
2035 assert(assigned_reg >= pd_first_cpu_reg && assigned_reg <= pd_last_cpu_reg, "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2036 assert(num_physical_regs(T_LONG) == 1 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2037 (assigned_regHi >= pd_first_cpu_reg && assigned_regHi <= pd_last_cpu_reg), "no cpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2038
a61af66fc99e Initial load
duke
parents:
diff changeset
2039 assert(assigned_reg != assigned_regHi, "invalid allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2040 assert(num_physical_regs(T_LONG) == 1 || assigned_reg < assigned_regHi,
a61af66fc99e Initial load
duke
parents:
diff changeset
2041 "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
2042 assert((assigned_regHi != any_reg) ^ (num_physical_regs(T_LONG) == 1), "must be match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2043 if (requires_adjacent_regs(T_LONG)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2044 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == assigned_regHi, "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2045 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2046
a61af66fc99e Initial load
duke
parents:
diff changeset
2047 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2048 return LIR_OprFact::double_cpu(assigned_reg, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2049 #else
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2050 #if defined(SPARC) || defined(PPC)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2051 return LIR_OprFact::double_cpu(assigned_regHi, assigned_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2052 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2053 return LIR_OprFact::double_cpu(assigned_reg, assigned_regHi);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2054 #endif // SPARC
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2055 #endif // LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2056 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2057
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2058 #ifndef __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2059 case T_FLOAT: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2060 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2061 if (UseSSE >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2062 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2063 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2064 return LIR_OprFact::single_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2065 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2066 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2067
a61af66fc99e Initial load
duke
parents:
diff changeset
2068 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2069 assert(interval->assigned_regHi() == any_reg, "must not have hi register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2070 return LIR_OprFact::single_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2071 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2072
a61af66fc99e Initial load
duke
parents:
diff changeset
2073 case T_DOUBLE: {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2074 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2075 if (UseSSE >= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2076 assert(assigned_reg >= pd_first_xmm_reg && assigned_reg <= pd_last_xmm_reg, "no xmm register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2077 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
2078 return LIR_OprFact::double_xmm(assigned_reg - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2079 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2080 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2081
a61af66fc99e Initial load
duke
parents:
diff changeset
2082 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2083 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2084 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
2085 assert(assigned_reg % 2 == 0 && assigned_reg + 1 == interval->assigned_regHi(), "must be sequential and even");
a61af66fc99e Initial load
duke
parents:
diff changeset
2086 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
2087 #elif defined(ARM)
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2088 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
2089 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
2090 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
2091 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
2092 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2093 assert(assigned_reg >= pd_first_fpu_reg && assigned_reg <= pd_last_fpu_reg, "no fpu register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2094 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
2095 LIR_Opr result = LIR_OprFact::double_fpu(assigned_reg - pd_first_fpu_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2096 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2097 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
2098 }
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2099 #endif // __SOFTFP__
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2100
a61af66fc99e Initial load
duke
parents:
diff changeset
2101 default: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2102 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2103 return LIR_OprFact::illegalOpr;
a61af66fc99e Initial load
duke
parents:
diff changeset
2104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2105 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2106 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2107 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2108
a61af66fc99e Initial load
duke
parents:
diff changeset
2109 LIR_Opr LinearScan::canonical_spill_opr(Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2110 assert(interval->canonical_spill_slot() >= nof_regs, "canonical spill slot not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2111 return LIR_OprFact::stack(interval->canonical_spill_slot() - nof_regs, interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2113
a61af66fc99e Initial load
duke
parents:
diff changeset
2114 LIR_Opr LinearScan::color_lir_opr(LIR_Opr opr, int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2115 assert(opr->is_virtual(), "should not call this otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2116
a61af66fc99e Initial load
duke
parents:
diff changeset
2117 Interval* interval = interval_at(opr->vreg_number());
a61af66fc99e Initial load
duke
parents:
diff changeset
2118 assert(interval != NULL, "interval must exist");
a61af66fc99e Initial load
duke
parents:
diff changeset
2119
a61af66fc99e Initial load
duke
parents:
diff changeset
2120 if (op_id != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2121 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2122 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2123 if (block->number_of_sux() <= 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2124 // check if spill moves could have been appended at the end of this block, but
a61af66fc99e Initial load
duke
parents:
diff changeset
2125 // before the branch instruction. So the split child information for this branch would
a61af66fc99e Initial load
duke
parents:
diff changeset
2126 // be incorrect.
a61af66fc99e Initial load
duke
parents:
diff changeset
2127 LIR_OpBranch* branch = block->lir()->instructions_list()->last()->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
2128 if (branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2129 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2130 assert(branch->cond() == lir_cond_always, "block does not end with an unconditional jump");
a61af66fc99e Initial load
duke
parents:
diff changeset
2131 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
2132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2133 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2135 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2136
a61af66fc99e Initial load
duke
parents:
diff changeset
2137 // operands are not changed when an interval is split during allocation,
a61af66fc99e Initial load
duke
parents:
diff changeset
2138 // so search the right interval here
a61af66fc99e Initial load
duke
parents:
diff changeset
2139 interval = split_child_at_op_id(interval, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2141
a61af66fc99e Initial load
duke
parents:
diff changeset
2142 LIR_Opr res = operand_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2143
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2144 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2145 // new semantic for is_last_use: not only set on definite end of interval,
a61af66fc99e Initial load
duke
parents:
diff changeset
2146 // but also before hole
a61af66fc99e Initial load
duke
parents:
diff changeset
2147 // 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
2148 // last use information is completely correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2149 // information is only needed for fpu stack allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
2150 if (res->is_fpu_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2151 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
2152 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
2153 res = res->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
2154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2156 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2157
a61af66fc99e Initial load
duke
parents:
diff changeset
2158 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
2159
a61af66fc99e Initial load
duke
parents:
diff changeset
2160 return res;
a61af66fc99e Initial load
duke
parents:
diff changeset
2161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2162
a61af66fc99e Initial load
duke
parents:
diff changeset
2163
a61af66fc99e Initial load
duke
parents:
diff changeset
2164 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2165 // some methods used to check correctness of debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2166
a61af66fc99e Initial load
duke
parents:
diff changeset
2167 void assert_no_register_values(GrowableArray<ScopeValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2168 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2169 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2171
a61af66fc99e Initial load
duke
parents:
diff changeset
2172 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2173 ScopeValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2174
a61af66fc99e Initial load
duke
parents:
diff changeset
2175 if (value->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2176 Location location = ((LocationValue*)value)->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2177 assert(location.where() == Location::on_stack, "value is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2179 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2181
a61af66fc99e Initial load
duke
parents:
diff changeset
2182 void assert_no_register_values(GrowableArray<MonitorValue*>* values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2183 if (values == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2184 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
2185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2186
a61af66fc99e Initial load
duke
parents:
diff changeset
2187 for (int i = 0; i < values->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2188 MonitorValue* value = values->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2189
a61af66fc99e Initial load
duke
parents:
diff changeset
2190 if (value->owner()->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2191 Location location = ((LocationValue*)value->owner())->location();
a61af66fc99e Initial load
duke
parents:
diff changeset
2192 assert(location.where() == Location::on_stack, "owner is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2194 assert(value->basic_lock().where() == Location::on_stack, "basic_lock is in register");
a61af66fc99e Initial load
duke
parents:
diff changeset
2195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2196 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2197
a61af66fc99e Initial load
duke
parents:
diff changeset
2198 void assert_equal(Location l1, Location l2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2199 assert(l1.where() == l2.where() && l1.type() == l2.type() && l1.offset() == l2.offset(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2201
a61af66fc99e Initial load
duke
parents:
diff changeset
2202 void assert_equal(ScopeValue* v1, ScopeValue* v2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2203 if (v1->is_location()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2204 assert(v2->is_location(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2205 assert_equal(((LocationValue*)v1)->location(), ((LocationValue*)v2)->location());
a61af66fc99e Initial load
duke
parents:
diff changeset
2206 } else if (v1->is_constant_int()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2207 assert(v2->is_constant_int(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2208 assert(((ConstantIntValue*)v1)->value() == ((ConstantIntValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2209 } else if (v1->is_constant_double()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2210 assert(v2->is_constant_double(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2211 assert(((ConstantDoubleValue*)v1)->value() == ((ConstantDoubleValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2212 } else if (v1->is_constant_long()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2213 assert(v2->is_constant_long(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2214 assert(((ConstantLongValue*)v1)->value() == ((ConstantLongValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2215 } else if (v1->is_constant_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2216 assert(v2->is_constant_oop(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2217 assert(((ConstantOopWriteValue*)v1)->value() == ((ConstantOopWriteValue*)v2)->value(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
2218 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2219 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2221 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2222
a61af66fc99e Initial load
duke
parents:
diff changeset
2223 void assert_equal(MonitorValue* m1, MonitorValue* m2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2224 assert_equal(m1->owner(), m2->owner());
a61af66fc99e Initial load
duke
parents:
diff changeset
2225 assert_equal(m1->basic_lock(), m2->basic_lock());
a61af66fc99e Initial load
duke
parents:
diff changeset
2226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2227
a61af66fc99e Initial load
duke
parents:
diff changeset
2228 void assert_equal(IRScopeDebugInfo* d1, IRScopeDebugInfo* d2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2229 assert(d1->scope() == d2->scope(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2230 assert(d1->bci() == d2->bci(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2231
a61af66fc99e Initial load
duke
parents:
diff changeset
2232 if (d1->locals() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2233 assert(d1->locals() != NULL && d2->locals() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2234 assert(d1->locals()->length() == d2->locals()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2235 for (int i = 0; i < d1->locals()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2236 assert_equal(d1->locals()->at(i), d2->locals()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2238 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2239 assert(d1->locals() == NULL && d2->locals() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2241
a61af66fc99e Initial load
duke
parents:
diff changeset
2242 if (d1->expressions() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2243 assert(d1->expressions() != NULL && d2->expressions() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2244 assert(d1->expressions()->length() == d2->expressions()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2245 for (int i = 0; i < d1->expressions()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2246 assert_equal(d1->expressions()->at(i), d2->expressions()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2247 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2248 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2249 assert(d1->expressions() == NULL && d2->expressions() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2251
a61af66fc99e Initial load
duke
parents:
diff changeset
2252 if (d1->monitors() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2253 assert(d1->monitors() != NULL && d2->monitors() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2254 assert(d1->monitors()->length() == d2->monitors()->length(), "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2255 for (int i = 0; i < d1->monitors()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2256 assert_equal(d1->monitors()->at(i), d2->monitors()->at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2258 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2259 assert(d1->monitors() == NULL && d2->monitors() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2260 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2261
a61af66fc99e Initial load
duke
parents:
diff changeset
2262 if (d1->caller() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2263 assert(d1->caller() != NULL && d2->caller() != NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2264 assert_equal(d1->caller(), d2->caller());
a61af66fc99e Initial load
duke
parents:
diff changeset
2265 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2266 assert(d1->caller() == NULL && d2->caller() == NULL, "not equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
2267 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2268 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2269
a61af66fc99e Initial load
duke
parents:
diff changeset
2270 void check_stack_depth(CodeEmitInfo* info, int stack_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2271 if (info->bci() != SynchronizationEntryBCI && !info->scope()->method()->is_native()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2272 Bytecodes::Code code = info->scope()->method()->java_code_at_bci(info->bci());
a61af66fc99e Initial load
duke
parents:
diff changeset
2273 switch (code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2274 case Bytecodes::_ifnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2275 case Bytecodes::_ifnonnull : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2276 case Bytecodes::_ifeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2277 case Bytecodes::_ifne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2278 case Bytecodes::_iflt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2279 case Bytecodes::_ifge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2280 case Bytecodes::_ifgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2281 case Bytecodes::_ifle : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2282 case Bytecodes::_if_icmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2283 case Bytecodes::_if_icmpne : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2284 case Bytecodes::_if_icmplt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2285 case Bytecodes::_if_icmpge : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2286 case Bytecodes::_if_icmpgt : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2287 case Bytecodes::_if_icmple : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2288 case Bytecodes::_if_acmpeq : // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2289 case Bytecodes::_if_acmpne :
a61af66fc99e Initial load
duke
parents:
diff changeset
2290 assert(stack_end >= -Bytecodes::depth(code), "must have non-empty expression stack at if bytecode");
a61af66fc99e Initial load
duke
parents:
diff changeset
2291 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2293 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2295
a61af66fc99e Initial load
duke
parents:
diff changeset
2296 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2297
a61af66fc99e Initial load
duke
parents:
diff changeset
2298
a61af66fc99e Initial load
duke
parents:
diff changeset
2299 IntervalWalker* LinearScan::init_compute_oop_maps() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2300 // setup lists of potential oops for walking
a61af66fc99e Initial load
duke
parents:
diff changeset
2301 Interval* oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2302 Interval* non_oop_intervals;
a61af66fc99e Initial load
duke
parents:
diff changeset
2303
a61af66fc99e Initial load
duke
parents:
diff changeset
2304 create_unhandled_lists(&oop_intervals, &non_oop_intervals, is_oop_interval, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2305
a61af66fc99e Initial load
duke
parents:
diff changeset
2306 // intervals that have no oops inside need not to be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
2307 // to ensure a walking until the last instruction id, add a dummy interval
a61af66fc99e Initial load
duke
parents:
diff changeset
2308 // with a high operation id
a61af66fc99e Initial load
duke
parents:
diff changeset
2309 non_oop_intervals = new Interval(any_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
2310 non_oop_intervals->add_range(max_jint - 2, max_jint - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2311
a61af66fc99e Initial load
duke
parents:
diff changeset
2312 return new IntervalWalker(this, oop_intervals, non_oop_intervals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2313 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2314
a61af66fc99e Initial load
duke
parents:
diff changeset
2315
a61af66fc99e Initial load
duke
parents:
diff changeset
2316 OopMap* LinearScan::compute_oop_map(IntervalWalker* iw, LIR_Op* op, CodeEmitInfo* info, bool is_call_site) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2317 TRACE_LINEAR_SCAN(3, tty->print_cr("creating oop map at op_id %d", op->id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2318
a61af66fc99e Initial load
duke
parents:
diff changeset
2319 // walk before the current operation -> intervals that start at
a61af66fc99e Initial load
duke
parents:
diff changeset
2320 // the operation (= output operands of the operation) are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2321 // included in the oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2322 iw->walk_before(op->id());
a61af66fc99e Initial load
duke
parents:
diff changeset
2323
a61af66fc99e Initial load
duke
parents:
diff changeset
2324 int frame_size = frame_map()->framesize();
a61af66fc99e Initial load
duke
parents:
diff changeset
2325 int arg_count = frame_map()->oop_map_arg_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2326 OopMap* map = new OopMap(frame_size, arg_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
2327
a61af66fc99e Initial load
duke
parents:
diff changeset
2328 // Check if this is a patch site.
a61af66fc99e Initial load
duke
parents:
diff changeset
2329 bool is_patch_info = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2330 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2331 assert(!is_call_site, "move must not be a call site");
a61af66fc99e Initial load
duke
parents:
diff changeset
2332 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2333 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2334
a61af66fc99e Initial load
duke
parents:
diff changeset
2335 is_patch_info = move->patch_code() != lir_patch_none;
a61af66fc99e Initial load
duke
parents:
diff changeset
2336 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2337
a61af66fc99e Initial load
duke
parents:
diff changeset
2338 // Iterate through active intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2339 for (Interval* interval = iw->active_first(fixedKind); interval != Interval::end(); interval = interval->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2340 int assigned_reg = interval->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2341
a61af66fc99e Initial load
duke
parents:
diff changeset
2342 assert(interval->current_from() <= op->id() && op->id() <= interval->current_to(), "interval should not be active otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2343 assert(interval->assigned_regHi() == any_reg, "oop must be single word");
a61af66fc99e Initial load
duke
parents:
diff changeset
2344 assert(interval->reg_num() >= LIR_OprDesc::vreg_base, "fixed interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
2345
a61af66fc99e Initial load
duke
parents:
diff changeset
2346 // Check if this range covers the instruction. Intervals that
a61af66fc99e Initial load
duke
parents:
diff changeset
2347 // start or end at the current operation are not included in the
a61af66fc99e Initial load
duke
parents:
diff changeset
2348 // oop map, except in the case of patching moves. For patching
a61af66fc99e Initial load
duke
parents:
diff changeset
2349 // moves, any intervals which end at this instruction are included
a61af66fc99e Initial load
duke
parents:
diff changeset
2350 // in the oop map since we may safepoint while doing the patch
a61af66fc99e Initial load
duke
parents:
diff changeset
2351 // before we've consumed the inputs.
a61af66fc99e Initial load
duke
parents:
diff changeset
2352 if (is_patch_info || op->id() < interval->current_to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2353
a61af66fc99e Initial load
duke
parents:
diff changeset
2354 // caller-save registers must not be included into oop-maps at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
2355 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
2356
a61af66fc99e Initial load
duke
parents:
diff changeset
2357 VMReg name = vm_reg_for_interval(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
2358 map->set_oop(name);
a61af66fc99e Initial load
duke
parents:
diff changeset
2359
a61af66fc99e Initial load
duke
parents:
diff changeset
2360 // Spill optimization: when the stack value is guaranteed to be always correct,
a61af66fc99e Initial load
duke
parents:
diff changeset
2361 // 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
2362 if (interval->always_in_memory() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2363 op->id() > interval->spill_definition_pos() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2364 interval->assigned_reg() != interval->canonical_spill_slot()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2365 assert(interval->spill_definition_pos() > 0, "position not set correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
2366 assert(interval->canonical_spill_slot() >= LinearScan::nof_regs, "no spill slot assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
2367 assert(interval->assigned_reg() < LinearScan::nof_regs, "interval is on stack, so stack slot is registered twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
2368
a61af66fc99e Initial load
duke
parents:
diff changeset
2369 map->set_oop(frame_map()->slot_regname(interval->canonical_spill_slot() - LinearScan::nof_regs));
a61af66fc99e Initial load
duke
parents:
diff changeset
2370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2372 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2373
a61af66fc99e Initial load
duke
parents:
diff changeset
2374 // add oops from lock stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2375 assert(info->stack() != NULL, "CodeEmitInfo must always have a stack");
a61af66fc99e Initial load
duke
parents:
diff changeset
2376 int locks_count = info->stack()->locks_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2377 for (int i = 0; i < locks_count; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2378 map->set_oop(frame_map()->monitor_object_regname(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2380
a61af66fc99e Initial load
duke
parents:
diff changeset
2381 return map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2383
a61af66fc99e Initial load
duke
parents:
diff changeset
2384
a61af66fc99e Initial load
duke
parents:
diff changeset
2385 void LinearScan::compute_oop_map(IntervalWalker* iw, const LIR_OpVisitState &visitor, LIR_Op* op) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2386 assert(visitor.info_count() > 0, "no oop map needed");
a61af66fc99e Initial load
duke
parents:
diff changeset
2387
a61af66fc99e Initial load
duke
parents:
diff changeset
2388 // compute oop_map only for first CodeEmitInfo
a61af66fc99e Initial load
duke
parents:
diff changeset
2389 // because it is (in most cases) equal for all other infos of the same operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2390 CodeEmitInfo* first_info = visitor.info_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2391 OopMap* first_oop_map = compute_oop_map(iw, op, first_info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2392
a61af66fc99e Initial load
duke
parents:
diff changeset
2393 for (int i = 0; i < visitor.info_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2394 CodeEmitInfo* info = visitor.info_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2395 OopMap* oop_map = first_oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2396
a61af66fc99e Initial load
duke
parents:
diff changeset
2397 if (info->stack()->locks_size() != first_info->stack()->locks_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2398 // this info has a different number of locks then the precomputed oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2399 // (possible for lock and unlock instructions) -> compute oop map with
a61af66fc99e Initial load
duke
parents:
diff changeset
2400 // correct lock information
a61af66fc99e Initial load
duke
parents:
diff changeset
2401 oop_map = compute_oop_map(iw, op, info, visitor.has_call());
a61af66fc99e Initial load
duke
parents:
diff changeset
2402 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2403
a61af66fc99e Initial load
duke
parents:
diff changeset
2404 if (info->_oop_map == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2405 info->_oop_map = oop_map;
a61af66fc99e Initial load
duke
parents:
diff changeset
2406 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2407 // a CodeEmitInfo can not be shared between different LIR-instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2408 // because interval splitting can occur anywhere between two instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
2409 // and so the oop maps must be different
a61af66fc99e Initial load
duke
parents:
diff changeset
2410 // -> check if the already set oop_map is exactly the one calculated for this operation
a61af66fc99e Initial load
duke
parents:
diff changeset
2411 assert(info->_oop_map == oop_map, "same CodeEmitInfo used for multiple LIR instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
2412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2413 }
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 // frequently used constants
a61af66fc99e Initial load
duke
parents:
diff changeset
2418 ConstantOopWriteValue LinearScan::_oop_null_scope_value = ConstantOopWriteValue(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2419 ConstantIntValue LinearScan::_int_m1_scope_value = ConstantIntValue(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2420 ConstantIntValue LinearScan::_int_0_scope_value = ConstantIntValue(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2421 ConstantIntValue LinearScan::_int_1_scope_value = ConstantIntValue(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2422 ConstantIntValue LinearScan::_int_2_scope_value = ConstantIntValue(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
2423 LocationValue _illegal_value = LocationValue(Location());
a61af66fc99e Initial load
duke
parents:
diff changeset
2424
a61af66fc99e Initial load
duke
parents:
diff changeset
2425 void LinearScan::init_compute_debug_info() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2426 // cache for frequently used scope values
a61af66fc99e Initial load
duke
parents:
diff changeset
2427 // (cpu registers and stack slots)
a61af66fc99e Initial load
duke
parents:
diff changeset
2428 _scope_value_cache = ScopeValueArray((LinearScan::nof_cpu_regs + frame_map()->argcount() + max_spills()) * 2, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2430
a61af66fc99e Initial load
duke
parents:
diff changeset
2431 MonitorValue* LinearScan::location_for_monitor_index(int monitor_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2432 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2433 if (!frame_map()->location_for_monitor_object(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2434 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2436 ScopeValue* object_scope_value = new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2437
a61af66fc99e Initial load
duke
parents:
diff changeset
2438 if (!frame_map()->location_for_monitor_lock(monitor_index, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2439 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2440 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2441 return new MonitorValue(object_scope_value, loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2442 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2443
a61af66fc99e Initial load
duke
parents:
diff changeset
2444 LocationValue* LinearScan::location_for_name(int name, Location::Type loc_type) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2445 Location loc;
a61af66fc99e Initial load
duke
parents:
diff changeset
2446 if (!frame_map()->locations_for_slot(name, loc_type, &loc)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2447 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2449 return new LocationValue(loc);
a61af66fc99e Initial load
duke
parents:
diff changeset
2450 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2451
a61af66fc99e Initial load
duke
parents:
diff changeset
2452
a61af66fc99e Initial load
duke
parents:
diff changeset
2453 int LinearScan::append_scope_value_for_constant(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2454 assert(opr->is_constant(), "should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
2455
a61af66fc99e Initial load
duke
parents:
diff changeset
2456 LIR_Const* c = opr->as_constant_ptr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2457 BasicType t = c->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
2458 switch (t) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2459 case T_OBJECT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2460 jobject value = c->as_jobject();
a61af66fc99e Initial load
duke
parents:
diff changeset
2461 if (value == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2462 scope_values->append(&_oop_null_scope_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
2463 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2464 scope_values->append(new ConstantOopWriteValue(c->as_jobject()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2466 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2467 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2468
a61af66fc99e Initial load
duke
parents:
diff changeset
2469 case T_INT: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2470 case T_FLOAT: {
a61af66fc99e Initial load
duke
parents:
diff changeset
2471 int value = c->as_jint_bits();
a61af66fc99e Initial load
duke
parents:
diff changeset
2472 switch (value) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2473 case -1: scope_values->append(&_int_m1_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2474 case 0: scope_values->append(&_int_0_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2475 case 1: scope_values->append(&_int_1_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2476 case 2: scope_values->append(&_int_2_scope_value); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2477 default: scope_values->append(new ConstantIntValue(c->as_jint_bits())); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
2478 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2479 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2480 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2481
a61af66fc99e Initial load
duke
parents:
diff changeset
2482 case T_LONG: // fall through
a61af66fc99e Initial load
duke
parents:
diff changeset
2483 case T_DOUBLE: {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2484 #ifdef _LP64
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2485 scope_values->append(&_int_0_scope_value);
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2486 scope_values->append(new ConstantLongValue(c->as_jlong_bits()));
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2487 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2488 if (hi_word_offset_in_bytes > lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2489 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2490 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2491 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2492 scope_values->append(new ConstantIntValue(c->as_jint_lo_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2493 scope_values->append(new ConstantIntValue(c->as_jint_hi_bits()));
a61af66fc99e Initial load
duke
parents:
diff changeset
2494 }
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2495 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2496 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2497 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2498
1297
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2499 case T_ADDRESS: {
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2500 #ifdef _LP64
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2501 scope_values->append(new ConstantLongValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2502 #else
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2503 scope_values->append(new ConstantIntValue(c->as_jint()));
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2504 #endif
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2505 return 1;
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2506 }
c466efa608d5 6932496: c1: deoptimization of jsr subroutine fails on sparcv9
roland
parents: 1060
diff changeset
2507
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2508 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
2509 ShouldNotReachHere();
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2510 return -1;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2511 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2513
a61af66fc99e Initial load
duke
parents:
diff changeset
2514 int LinearScan::append_scope_value_for_operand(LIR_Opr opr, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2515 if (opr->is_single_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2516 int stack_idx = opr->single_stack_ix();
a61af66fc99e Initial load
duke
parents:
diff changeset
2517 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2518 int cache_idx = (stack_idx + LinearScan::nof_cpu_regs) * 2 + (is_oop ? 1 : 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
2519
a61af66fc99e Initial load
duke
parents:
diff changeset
2520 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2521 if (sv == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2522 Location::Type loc_type = is_oop ? Location::oop : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2523 sv = location_for_name(stack_idx, loc_type);
a61af66fc99e Initial load
duke
parents:
diff changeset
2524 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2525 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2526
a61af66fc99e Initial load
duke
parents:
diff changeset
2527 // check if cached value is correct
a61af66fc99e Initial load
duke
parents:
diff changeset
2528 DEBUG_ONLY(assert_equal(sv, location_for_name(stack_idx, is_oop ? Location::oop : Location::normal)));
a61af66fc99e Initial load
duke
parents:
diff changeset
2529
a61af66fc99e Initial load
duke
parents:
diff changeset
2530 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2531 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2532
a61af66fc99e Initial load
duke
parents:
diff changeset
2533 } else if (opr->is_single_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2534 bool is_oop = opr->is_oop_register();
a61af66fc99e Initial load
duke
parents:
diff changeset
2535 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
2536 Location::Type int_loc_type = NOT_LP64(Location::normal) LP64_ONLY(Location::int_in_long);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2537
a61af66fc99e Initial load
duke
parents:
diff changeset
2538 ScopeValue* sv = _scope_value_cache.at(cache_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
2539 if (sv == NULL) {
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2540 Location::Type loc_type = is_oop ? Location::oop : int_loc_type;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2541 VMReg rname = frame_map()->regname(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2542 sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2543 _scope_value_cache.at_put(cache_idx, sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2545
a61af66fc99e Initial load
duke
parents:
diff changeset
2546 // check if cached value is correct
1060
323bd24c6520 6769124: various 64-bit fixes for c1
roland
parents: 844
diff changeset
2547 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
2548
a61af66fc99e Initial load
duke
parents:
diff changeset
2549 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2550 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2551
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2552 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2553 } else if (opr->is_single_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2554 VMReg rname = opr->as_xmm_float_reg()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2555 LocationValue* sv = new LocationValue(Location::new_reg_loc(Location::normal, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2556
a61af66fc99e Initial load
duke
parents:
diff changeset
2557 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2558 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2559 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2560
a61af66fc99e Initial load
duke
parents:
diff changeset
2561 } else if (opr->is_single_fpu()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2562 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2563 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2564 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2565 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2566 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
2567 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2568 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2569 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2570
a61af66fc99e Initial load
duke
parents:
diff changeset
2571 Location::Type loc_type = float_saved_as_double ? Location::float_in_dbl : Location::normal;
a61af66fc99e Initial load
duke
parents:
diff changeset
2572 VMReg rname = frame_map()->fpu_regname(opr->fpu_regnr());
a61af66fc99e Initial load
duke
parents:
diff changeset
2573 LocationValue* sv = new LocationValue(Location::new_reg_loc(loc_type, rname));
a61af66fc99e Initial load
duke
parents:
diff changeset
2574
a61af66fc99e Initial load
duke
parents:
diff changeset
2575 scope_values->append(sv);
a61af66fc99e Initial load
duke
parents:
diff changeset
2576 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2577
a61af66fc99e Initial load
duke
parents:
diff changeset
2578 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2579 // double-size operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2580
a61af66fc99e Initial load
duke
parents:
diff changeset
2581 ScopeValue* first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2582 ScopeValue* second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2583
a61af66fc99e Initial load
duke
parents:
diff changeset
2584 if (opr->is_double_stack()) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2585 #ifdef _LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2586 Location loc1;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2587 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
2588 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
2589 bailout("too large frame");
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2590 }
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2591 // Does this reverse on x86 vs. sparc?
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2592 first = new LocationValue(loc1);
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2593 second = &_int_0_scope_value;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2594 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2595 Location loc1, loc2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2596 if (!frame_map()->locations_for_slot(opr->double_stack_ix(), Location::normal, &loc1, &loc2)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2597 bailout("too large frame");
a61af66fc99e Initial load
duke
parents:
diff changeset
2598 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2599 first = new LocationValue(loc1);
a61af66fc99e Initial load
duke
parents:
diff changeset
2600 second = new LocationValue(loc2);
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2601 #endif // _LP64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2602
a61af66fc99e Initial load
duke
parents:
diff changeset
2603 } else if (opr->is_double_cpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2604 #ifdef _LP64
a61af66fc99e Initial load
duke
parents:
diff changeset
2605 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2606 first = new LocationValue(Location::new_reg_loc(Location::lng, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2607 second = &_int_0_scope_value;
a61af66fc99e Initial load
duke
parents:
diff changeset
2608 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
2609 VMReg rname_first = opr->as_register_lo()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2610 VMReg rname_second = opr->as_register_hi()->as_VMReg();
a61af66fc99e Initial load
duke
parents:
diff changeset
2611
a61af66fc99e Initial load
duke
parents:
diff changeset
2612 if (hi_word_offset_in_bytes < lo_word_offset_in_bytes) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2613 // lo/hi and swapped relative to first and second, so swap them
a61af66fc99e Initial load
duke
parents:
diff changeset
2614 VMReg tmp = rname_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
2615 rname_first = rname_second;
a61af66fc99e Initial load
duke
parents:
diff changeset
2616 rname_second = tmp;
a61af66fc99e Initial load
duke
parents:
diff changeset
2617 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2618
a61af66fc99e Initial load
duke
parents:
diff changeset
2619 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2620 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
2621 #endif //_LP64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2622
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2623
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2624 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2625 } else if (opr->is_double_xmm()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2626 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
2627 VMReg rname_first = opr->as_xmm_double_reg()->as_VMReg();
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2628 # ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2629 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2630 second = &_int_0_scope_value;
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2631 # else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2632 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2633 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2634 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2635 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2636 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2637 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2638 # endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2639 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2640
a61af66fc99e Initial load
duke
parents:
diff changeset
2641 } else if (opr->is_double_fpu()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2642 // 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
2643 // the double as float registers in the native ordering. On X86,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2644 // fpu_regnrLo is a FPU stack slot whose VMReg represents
a61af66fc99e Initial load
duke
parents:
diff changeset
2645 // the low-order word of the double and fpu_regnrLo + 1 is the
a61af66fc99e Initial load
duke
parents:
diff changeset
2646 // name for the other half. *first and *second must represent the
a61af66fc99e Initial load
duke
parents:
diff changeset
2647 // least and most significant words, respectively.
a61af66fc99e Initial load
duke
parents:
diff changeset
2648
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
2649 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2650 // the exact location of fpu stack values is only known
a61af66fc99e Initial load
duke
parents:
diff changeset
2651 // during fpu stack allocation, so the stack allocator object
a61af66fc99e Initial load
duke
parents:
diff changeset
2652 // must be present
a61af66fc99e Initial load
duke
parents:
diff changeset
2653 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
2654 assert(_fpu_stack_allocator != NULL, "must be present");
a61af66fc99e Initial load
duke
parents:
diff changeset
2655 opr = _fpu_stack_allocator->to_fpu_stack(opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
2656
a61af66fc99e Initial load
duke
parents:
diff changeset
2657 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi(), "assumed in calculation (only fpu_regnrHi is used)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2658 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2659 #ifdef SPARC
a61af66fc99e Initial load
duke
parents:
diff changeset
2660 assert(opr->fpu_regnrLo() == opr->fpu_regnrHi() + 1, "assumed in calculation (only fpu_regnrHi is used)");
a61af66fc99e Initial load
duke
parents:
diff changeset
2661 #endif
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2662 #ifdef ARM
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2663 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
2664 #endif
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2665 #ifdef PPC
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
2666 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
2667 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2668
a61af66fc99e Initial load
duke
parents:
diff changeset
2669 VMReg rname_first = frame_map()->fpu_regname(opr->fpu_regnrHi());
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2670 #ifdef _LP64
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2671 first = new LocationValue(Location::new_reg_loc(Location::dbl, rname_first));
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2672 second = &_int_0_scope_value;
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2673 #else
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2674 first = new LocationValue(Location::new_reg_loc(Location::normal, rname_first));
a61af66fc99e Initial load
duke
parents:
diff changeset
2675 // %%% This is probably a waste but we'll keep things as they were for now
a61af66fc99e Initial load
duke
parents:
diff changeset
2676 if (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2677 VMReg rname_second = rname_first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
2678 second = new LocationValue(Location::new_reg_loc(Location::normal, rname_second));
a61af66fc99e Initial load
duke
parents:
diff changeset
2679 }
1369
0a43776437b6 6942223: c1 64 bit fixes
iveresov
parents: 1297
diff changeset
2680 #endif
0
a61af66fc99e Initial load
duke
parents:
diff changeset
2681
a61af66fc99e Initial load
duke
parents:
diff changeset
2682 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2683 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
2684 first = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2685 second = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2686 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2687
a61af66fc99e Initial load
duke
parents:
diff changeset
2688 assert(first != NULL && second != NULL, "must be set");
a61af66fc99e Initial load
duke
parents:
diff changeset
2689 // The convention the interpreter uses is that the second local
a61af66fc99e Initial load
duke
parents:
diff changeset
2690 // holds the first raw word of the native double representation.
a61af66fc99e Initial load
duke
parents:
diff changeset
2691 // This is actually reasonable, since locals and stack arrays
a61af66fc99e Initial load
duke
parents:
diff changeset
2692 // grow downwards in all implementations.
a61af66fc99e Initial load
duke
parents:
diff changeset
2693 // (If, on some machine, the interpreter's Java locals or stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2694 // were to grow upwards, the embedded doubles would be word-swapped.)
a61af66fc99e Initial load
duke
parents:
diff changeset
2695 scope_values->append(second);
a61af66fc99e Initial load
duke
parents:
diff changeset
2696 scope_values->append(first);
a61af66fc99e Initial load
duke
parents:
diff changeset
2697 return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
2698 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2699 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2700
a61af66fc99e Initial load
duke
parents:
diff changeset
2701
a61af66fc99e Initial load
duke
parents:
diff changeset
2702 int LinearScan::append_scope_value(int op_id, Value value, GrowableArray<ScopeValue*>* scope_values) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2703 if (value != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2704 LIR_Opr opr = value->operand();
a61af66fc99e Initial load
duke
parents:
diff changeset
2705 Constant* con = value->as_Constant();
a61af66fc99e Initial load
duke
parents:
diff changeset
2706
a61af66fc99e Initial load
duke
parents:
diff changeset
2707 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
2708 assert(con != NULL || opr->is_virtual(), "asumption: non-Constant instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2709
a61af66fc99e Initial load
duke
parents:
diff changeset
2710 if (con != NULL && !con->is_pinned() && !opr->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2711 // Unpinned constants may have a virtual operand for a part of the lifetime
a61af66fc99e Initial load
duke
parents:
diff changeset
2712 // or may be illegal when it was optimized away,
a61af66fc99e Initial load
duke
parents:
diff changeset
2713 // so always use a constant operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2714 opr = LIR_OprFact::value_type(con->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
2715 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2716 assert(opr->is_virtual() || opr->is_constant(), "other cases not allowed here");
a61af66fc99e Initial load
duke
parents:
diff changeset
2717
a61af66fc99e Initial load
duke
parents:
diff changeset
2718 if (opr->is_virtual()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2719 LIR_OpVisitState::OprMode mode = LIR_OpVisitState::inputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2720
a61af66fc99e Initial load
duke
parents:
diff changeset
2721 BlockBegin* block = block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2722 if (block->number_of_sux() == 1 && op_id == block->last_lir_instruction_id()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2723 // generating debug information for the last instruction of a block.
a61af66fc99e Initial load
duke
parents:
diff changeset
2724 // if this instruction is a branch, spill moves are inserted before this branch
a61af66fc99e Initial load
duke
parents:
diff changeset
2725 // and so the wrong operand would be returned (spill moves at block boundaries are not
a61af66fc99e Initial load
duke
parents:
diff changeset
2726 // considered in the live ranges of intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
2727 // Solution: use the first op_id of the branch target block instead.
a61af66fc99e Initial load
duke
parents:
diff changeset
2728 if (block->lir()->instructions_list()->last()->as_OpBranch() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2729 if (block->live_out().at(opr->vreg_number())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2730 op_id = block->sux_at(0)->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2731 mode = LIR_OpVisitState::outputMode;
a61af66fc99e Initial load
duke
parents:
diff changeset
2732 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2733 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2734 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2735
a61af66fc99e Initial load
duke
parents:
diff changeset
2736 // Get current location of operand
a61af66fc99e Initial load
duke
parents:
diff changeset
2737 // The operand must be live because debug information is considered when building the intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
2738 // if the interval is not live, color_lir_opr will cause an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
2739 opr = color_lir_opr(opr, op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2740 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
2741
a61af66fc99e Initial load
duke
parents:
diff changeset
2742 // Append to ScopeValue array
a61af66fc99e Initial load
duke
parents:
diff changeset
2743 return append_scope_value_for_operand(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2744
a61af66fc99e Initial load
duke
parents:
diff changeset
2745 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2746 assert(value->as_Constant() != NULL, "all other instructions have only virtual operands");
a61af66fc99e Initial load
duke
parents:
diff changeset
2747 assert(opr->is_constant(), "operand must be constant");
a61af66fc99e Initial load
duke
parents:
diff changeset
2748
a61af66fc99e Initial load
duke
parents:
diff changeset
2749 return append_scope_value_for_constant(opr, scope_values);
a61af66fc99e Initial load
duke
parents:
diff changeset
2750 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2751 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2752 // append a dummy value because real value not needed
a61af66fc99e Initial load
duke
parents:
diff changeset
2753 scope_values->append(&_illegal_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
2754 return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
2755 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2756 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2757
a61af66fc99e Initial load
duke
parents:
diff changeset
2758
a61af66fc99e Initial load
duke
parents:
diff changeset
2759 IRScopeDebugInfo* LinearScan::compute_debug_info_for_scope(int op_id, IRScope* cur_scope, ValueStack* cur_state, ValueStack* innermost_state, int cur_bci, int stack_end, int locks_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2760 IRScopeDebugInfo* caller_debug_info = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2761 int stack_begin, locks_begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
2762
a61af66fc99e Initial load
duke
parents:
diff changeset
2763 ValueStack* caller_state = cur_scope->caller_state();
a61af66fc99e Initial load
duke
parents:
diff changeset
2764 if (caller_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2765 // process recursively to compute outermost scope first
a61af66fc99e Initial load
duke
parents:
diff changeset
2766 stack_begin = caller_state->stack_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2767 locks_begin = caller_state->locks_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2768 caller_debug_info = compute_debug_info_for_scope(op_id, cur_scope->caller(), caller_state, innermost_state, cur_scope->caller_bci(), stack_begin, locks_begin);
a61af66fc99e Initial load
duke
parents:
diff changeset
2769 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2770 stack_begin = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2771 locks_begin = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2772 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2773
a61af66fc99e Initial load
duke
parents:
diff changeset
2774 // initialize these to null.
a61af66fc99e Initial load
duke
parents:
diff changeset
2775 // If we don't need deopt info or there are no locals, expressions or monitors,
a61af66fc99e Initial load
duke
parents:
diff changeset
2776 // then these get recorded as no information and avoids the allocation of 0 length arrays.
a61af66fc99e Initial load
duke
parents:
diff changeset
2777 GrowableArray<ScopeValue*>* locals = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2778 GrowableArray<ScopeValue*>* expressions = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2779 GrowableArray<MonitorValue*>* monitors = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
2780
a61af66fc99e Initial load
duke
parents:
diff changeset
2781 // describe local variable values
a61af66fc99e Initial load
duke
parents:
diff changeset
2782 int nof_locals = cur_scope->method()->max_locals();
a61af66fc99e Initial load
duke
parents:
diff changeset
2783 if (nof_locals > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2784 locals = new GrowableArray<ScopeValue*>(nof_locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2785
a61af66fc99e Initial load
duke
parents:
diff changeset
2786 int pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2787 while (pos < nof_locals) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2788 assert(pos < cur_state->locals_size(), "why not?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2789
a61af66fc99e Initial load
duke
parents:
diff changeset
2790 Value local = cur_state->local_at(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2791 pos += append_scope_value(op_id, local, locals);
a61af66fc99e Initial load
duke
parents:
diff changeset
2792
a61af66fc99e Initial load
duke
parents:
diff changeset
2793 assert(locals->length() == pos, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2794 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2795 assert(locals->length() == cur_scope->method()->max_locals(), "wrong number of locals");
a61af66fc99e Initial load
duke
parents:
diff changeset
2796 assert(locals->length() == cur_state->locals_size(), "wrong number of locals");
a61af66fc99e Initial load
duke
parents:
diff changeset
2797 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2798
a61af66fc99e Initial load
duke
parents:
diff changeset
2799
a61af66fc99e Initial load
duke
parents:
diff changeset
2800 // describe expression stack
a61af66fc99e Initial load
duke
parents:
diff changeset
2801 //
a61af66fc99e Initial load
duke
parents:
diff changeset
2802 // When we inline methods containing exception handlers, the
a61af66fc99e Initial load
duke
parents:
diff changeset
2803 // "lock_stacks" are changed to preserve expression stack values
a61af66fc99e Initial load
duke
parents:
diff changeset
2804 // in caller scopes when exception handlers are present. This
a61af66fc99e Initial load
duke
parents:
diff changeset
2805 // can cause callee stacks to be smaller than caller stacks.
a61af66fc99e Initial load
duke
parents:
diff changeset
2806 if (stack_end > innermost_state->stack_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2807 stack_end = innermost_state->stack_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2808 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2809
a61af66fc99e Initial load
duke
parents:
diff changeset
2810
a61af66fc99e Initial load
duke
parents:
diff changeset
2811
a61af66fc99e Initial load
duke
parents:
diff changeset
2812 int nof_stack = stack_end - stack_begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
2813 if (nof_stack > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2814 expressions = new GrowableArray<ScopeValue*>(nof_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
2815
a61af66fc99e Initial load
duke
parents:
diff changeset
2816 int pos = stack_begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
2817 while (pos < stack_end) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2818 Value expression = innermost_state->stack_at_inc(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
2819 append_scope_value(op_id, expression, expressions);
a61af66fc99e Initial load
duke
parents:
diff changeset
2820
a61af66fc99e Initial load
duke
parents:
diff changeset
2821 assert(expressions->length() + stack_begin == pos, "must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
2822 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2823 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2824
a61af66fc99e Initial load
duke
parents:
diff changeset
2825 // describe monitors
a61af66fc99e Initial load
duke
parents:
diff changeset
2826 assert(locks_begin <= locks_end, "error in scope iteration");
a61af66fc99e Initial load
duke
parents:
diff changeset
2827 int nof_locks = locks_end - locks_begin;
a61af66fc99e Initial load
duke
parents:
diff changeset
2828 if (nof_locks > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2829 monitors = new GrowableArray<MonitorValue*>(nof_locks);
a61af66fc99e Initial load
duke
parents:
diff changeset
2830 for (int i = locks_begin; i < locks_end; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2831 monitors->append(location_for_monitor_index(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
2832 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2833 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2834
a61af66fc99e Initial load
duke
parents:
diff changeset
2835 return new IRScopeDebugInfo(cur_scope, cur_bci, locals, expressions, monitors, caller_debug_info);
a61af66fc99e Initial load
duke
parents:
diff changeset
2836 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2837
a61af66fc99e Initial load
duke
parents:
diff changeset
2838
a61af66fc99e Initial load
duke
parents:
diff changeset
2839 void LinearScan::compute_debug_info(CodeEmitInfo* info, int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2840 TRACE_LINEAR_SCAN(3, tty->print_cr("creating debug information at op_id %d", op_id));
a61af66fc99e Initial load
duke
parents:
diff changeset
2841
a61af66fc99e Initial load
duke
parents:
diff changeset
2842 IRScope* innermost_scope = info->scope();
a61af66fc99e Initial load
duke
parents:
diff changeset
2843 ValueStack* innermost_state = info->stack();
a61af66fc99e Initial load
duke
parents:
diff changeset
2844
a61af66fc99e Initial load
duke
parents:
diff changeset
2845 assert(innermost_scope != NULL && innermost_state != NULL, "why is it missing?");
a61af66fc99e Initial load
duke
parents:
diff changeset
2846
a61af66fc99e Initial load
duke
parents:
diff changeset
2847 int stack_end = innermost_state->stack_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2848 int locks_end = innermost_state->locks_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
2849
a61af66fc99e Initial load
duke
parents:
diff changeset
2850 DEBUG_ONLY(check_stack_depth(info, stack_end));
a61af66fc99e Initial load
duke
parents:
diff changeset
2851
a61af66fc99e Initial load
duke
parents:
diff changeset
2852 if (info->_scope_debug_info == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2853 // compute debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2854 info->_scope_debug_info = compute_debug_info_for_scope(op_id, innermost_scope, innermost_state, innermost_state, info->bci(), stack_end, locks_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
2855 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2856 // debug information already set. Check that it is correct from the current point of view
a61af66fc99e Initial load
duke
parents:
diff changeset
2857 DEBUG_ONLY(assert_equal(info->_scope_debug_info, compute_debug_info_for_scope(op_id, innermost_scope, innermost_state, innermost_state, info->bci(), stack_end, locks_end)));
a61af66fc99e Initial load
duke
parents:
diff changeset
2858 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2860
a61af66fc99e Initial load
duke
parents:
diff changeset
2861
a61af66fc99e Initial load
duke
parents:
diff changeset
2862 void LinearScan::assign_reg_num(LIR_OpList* instructions, IntervalWalker* iw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2863 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
2864 int num_inst = instructions->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2865 bool has_dead = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
2866
a61af66fc99e Initial load
duke
parents:
diff changeset
2867 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2868 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
2869 if (op == NULL) { // this can happen when spill-moves are removed in eliminate_spill_moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2870 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2871 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
2872 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2873 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
2874
a61af66fc99e Initial load
duke
parents:
diff changeset
2875 // visit instruction to get list of operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2876 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2877
a61af66fc99e Initial load
duke
parents:
diff changeset
2878 // iterate all modes of the visitor and process all virtual operands
a61af66fc99e Initial load
duke
parents:
diff changeset
2879 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2880 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
2881 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2882 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2883 if (opr->is_virtual_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2884 visitor.set_opr_at(mode, k, color_lir_opr(opr, op_id, mode));
a61af66fc99e Initial load
duke
parents:
diff changeset
2885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2887 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2888
a61af66fc99e Initial load
duke
parents:
diff changeset
2889 if (visitor.info_count() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2890 // exception handling
a61af66fc99e Initial load
duke
parents:
diff changeset
2891 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2892 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
2893 int n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
2894 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2895 XHandler* handler = xhandlers->handler_at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
2896 if (handler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2897 assign_reg_num(handler->entry_code()->instructions_list(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2898 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2899 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2900 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
2901 assert(visitor.all_xhandler()->length() == 0, "missed exception handler");
a61af66fc99e Initial load
duke
parents:
diff changeset
2902 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2903
a61af66fc99e Initial load
duke
parents:
diff changeset
2904 // compute oop map
a61af66fc99e Initial load
duke
parents:
diff changeset
2905 assert(iw != NULL, "needed for compute_oop_map");
a61af66fc99e Initial load
duke
parents:
diff changeset
2906 compute_oop_map(iw, visitor, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2907
a61af66fc99e Initial load
duke
parents:
diff changeset
2908 // compute debug information
a61af66fc99e Initial load
duke
parents:
diff changeset
2909 if (!use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2910 // compute debug information if fpu stack allocation is not needed.
a61af66fc99e Initial load
duke
parents:
diff changeset
2911 // when fpu stack allocation is needed, the debug information can not
a61af66fc99e Initial load
duke
parents:
diff changeset
2912 // be computed here because the exact location of fpu operands is not known
a61af66fc99e Initial load
duke
parents:
diff changeset
2913 // -> debug information is created inside the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
2914 int n = visitor.info_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2915 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2916 compute_debug_info(visitor.info_at(k), op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
2917 }
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 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
2922 // make sure we haven't made the op invalid.
a61af66fc99e Initial load
duke
parents:
diff changeset
2923 op->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
2924 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
2925
a61af66fc99e Initial load
duke
parents:
diff changeset
2926 // remove useless moves
a61af66fc99e Initial load
duke
parents:
diff changeset
2927 if (op->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2928 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
2929 LIR_Op1* move = (LIR_Op1*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
2930 LIR_Opr src = move->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2931 LIR_Opr dst = move->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
2932 if (dst == src ||
a61af66fc99e Initial load
duke
parents:
diff changeset
2933 !dst->is_pointer() && !src->is_pointer() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
2934 src->is_same_register(dst)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2935 instructions->at_put(j, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
2936 has_dead = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
2937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2939 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2940
a61af66fc99e Initial load
duke
parents:
diff changeset
2941 if (has_dead) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2942 // iterate all instructions of the block and remove all null-values.
a61af66fc99e Initial load
duke
parents:
diff changeset
2943 int insert_point = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
2944 for (int j = 0; j < num_inst; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2945 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
2946 if (op != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2947 if (insert_point != j) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2948 instructions->at_put(insert_point, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
2949 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2950 insert_point++;
a61af66fc99e Initial load
duke
parents:
diff changeset
2951 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2952 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2953 instructions->truncate(insert_point);
a61af66fc99e Initial load
duke
parents:
diff changeset
2954 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2955 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2956
a61af66fc99e Initial load
duke
parents:
diff changeset
2957 void LinearScan::assign_reg_num() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2958 TIME_LINEAR_SCAN(timer_assign_reg_num);
a61af66fc99e Initial load
duke
parents:
diff changeset
2959
a61af66fc99e Initial load
duke
parents:
diff changeset
2960 init_compute_debug_info();
a61af66fc99e Initial load
duke
parents:
diff changeset
2961 IntervalWalker* iw = init_compute_oop_maps();
a61af66fc99e Initial load
duke
parents:
diff changeset
2962
a61af66fc99e Initial load
duke
parents:
diff changeset
2963 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
2964 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2965 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
2966 assign_reg_num(block->lir()->instructions_list(), iw);
a61af66fc99e Initial load
duke
parents:
diff changeset
2967 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2968 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2969
a61af66fc99e Initial load
duke
parents:
diff changeset
2970
a61af66fc99e Initial load
duke
parents:
diff changeset
2971 void LinearScan::do_linear_scan() {
a61af66fc99e Initial load
duke
parents:
diff changeset
2972 NOT_PRODUCT(_total_timer.begin_method());
a61af66fc99e Initial load
duke
parents:
diff changeset
2973
a61af66fc99e Initial load
duke
parents:
diff changeset
2974 number_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
2975
a61af66fc99e Initial load
duke
parents:
diff changeset
2976 NOT_PRODUCT(print_lir(1, "Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
2977
a61af66fc99e Initial load
duke
parents:
diff changeset
2978 compute_local_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
2979 compute_global_live_sets();
a61af66fc99e Initial load
duke
parents:
diff changeset
2980 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
2981
a61af66fc99e Initial load
duke
parents:
diff changeset
2982 build_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
2983 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
2984 sort_intervals_before_allocation();
a61af66fc99e Initial load
duke
parents:
diff changeset
2985
a61af66fc99e Initial load
duke
parents:
diff changeset
2986 NOT_PRODUCT(print_intervals("Before Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
2987 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_before_alloc));
a61af66fc99e Initial load
duke
parents:
diff changeset
2988
a61af66fc99e Initial load
duke
parents:
diff changeset
2989 allocate_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
2990 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
2991
a61af66fc99e Initial load
duke
parents:
diff changeset
2992 resolve_data_flow();
a61af66fc99e Initial load
duke
parents:
diff changeset
2993 if (compilation()->has_exception_handlers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
2994 resolve_exception_handlers();
a61af66fc99e Initial load
duke
parents:
diff changeset
2995 }
a61af66fc99e Initial load
duke
parents:
diff changeset
2996 // fill in number of spill slots into frame_map
a61af66fc99e Initial load
duke
parents:
diff changeset
2997 propagate_spill_slots();
a61af66fc99e Initial load
duke
parents:
diff changeset
2998 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
2999
a61af66fc99e Initial load
duke
parents:
diff changeset
3000 NOT_PRODUCT(print_intervals("After Register Allocation"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3001 NOT_PRODUCT(print_lir(2, "LIR after register allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3002
a61af66fc99e Initial load
duke
parents:
diff changeset
3003 sort_intervals_after_allocation();
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3004
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3005 DEBUG_ONLY(verify());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3006
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3007 eliminate_spill_moves();
a61af66fc99e Initial load
duke
parents:
diff changeset
3008 assign_reg_num();
a61af66fc99e Initial load
duke
parents:
diff changeset
3009 CHECK_BAILOUT();
a61af66fc99e Initial load
duke
parents:
diff changeset
3010
a61af66fc99e Initial load
duke
parents:
diff changeset
3011 NOT_PRODUCT(print_lir(2, "LIR after assignment of register numbers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3012 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_after_asign));
a61af66fc99e Initial load
duke
parents:
diff changeset
3013
a61af66fc99e Initial load
duke
parents:
diff changeset
3014 { TIME_LINEAR_SCAN(timer_allocate_fpu_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
3015
a61af66fc99e Initial load
duke
parents:
diff changeset
3016 if (use_fpu_stack_allocation()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3017 allocate_fpu_stack(); // Only has effect on Intel
a61af66fc99e Initial load
duke
parents:
diff changeset
3018 NOT_PRODUCT(print_lir(2, "LIR after FPU stack allocation:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3020 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3021
a61af66fc99e Initial load
duke
parents:
diff changeset
3022 { TIME_LINEAR_SCAN(timer_optimize_lir);
a61af66fc99e Initial load
duke
parents:
diff changeset
3023
a61af66fc99e Initial load
duke
parents:
diff changeset
3024 EdgeMoveOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3025 ControlFlowOptimizer::optimize(ir()->code());
a61af66fc99e Initial load
duke
parents:
diff changeset
3026 // check that cfg is still correct after optimizations
a61af66fc99e Initial load
duke
parents:
diff changeset
3027 ir()->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
3028 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3029
a61af66fc99e Initial load
duke
parents:
diff changeset
3030 NOT_PRODUCT(print_lir(1, "Before Code Generation", false));
a61af66fc99e Initial load
duke
parents:
diff changeset
3031 NOT_PRODUCT(LinearScanStatistic::compute(this, _stat_final));
a61af66fc99e Initial load
duke
parents:
diff changeset
3032 NOT_PRODUCT(_total_timer.end_method(this));
a61af66fc99e Initial load
duke
parents:
diff changeset
3033 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3034
a61af66fc99e Initial load
duke
parents:
diff changeset
3035
a61af66fc99e Initial load
duke
parents:
diff changeset
3036 // ********** Printing functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3037
a61af66fc99e Initial load
duke
parents:
diff changeset
3038 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3039
a61af66fc99e Initial load
duke
parents:
diff changeset
3040 void LinearScan::print_timers(double total) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3041 _total_timer.print(total);
a61af66fc99e Initial load
duke
parents:
diff changeset
3042 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3043
a61af66fc99e Initial load
duke
parents:
diff changeset
3044 void LinearScan::print_statistics() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3045 _stat_before_alloc.print("before allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3046 _stat_after_asign.print("after assignment of register");
a61af66fc99e Initial load
duke
parents:
diff changeset
3047 _stat_final.print("after optimization");
a61af66fc99e Initial load
duke
parents:
diff changeset
3048 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3049
a61af66fc99e Initial load
duke
parents:
diff changeset
3050 void LinearScan::print_bitmap(BitMap& b) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3051 for (unsigned int i = 0; i < b.size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3052 if (b.at(i)) tty->print("%d ", i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3053 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3054 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3055 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3056
a61af66fc99e Initial load
duke
parents:
diff changeset
3057 void LinearScan::print_intervals(const char* label) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3058 if (TraceLinearScanLevel >= 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3059 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3060 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3061 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3062
a61af66fc99e Initial load
duke
parents:
diff changeset
3063 for (i = 0; i < interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3064 Interval* interval = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3065 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3066 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
3067 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3068 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3069
a61af66fc99e Initial load
duke
parents:
diff changeset
3070 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3071 tty->print_cr("--- Basic Blocks ---");
a61af66fc99e Initial load
duke
parents:
diff changeset
3072 for (i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3073 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3074 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
3075 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3076 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3077 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3078 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3079
a61af66fc99e Initial load
duke
parents:
diff changeset
3080 if (PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3081 CFGPrinter::print_intervals(&_intervals, label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3082 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3083 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3084
a61af66fc99e Initial load
duke
parents:
diff changeset
3085 void LinearScan::print_lir(int level, const char* label, bool hir_valid) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3086 if (TraceLinearScanLevel >= level) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3087 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3088 tty->print_cr("%s", label);
a61af66fc99e Initial load
duke
parents:
diff changeset
3089 print_LIR(ir()->linear_scan_order());
a61af66fc99e Initial load
duke
parents:
diff changeset
3090 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3091 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3092
a61af66fc99e Initial load
duke
parents:
diff changeset
3093 if (level == 1 && PrintCFGToFile) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3094 CFGPrinter::print_cfg(ir()->linear_scan_order(), label, hir_valid, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3095 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3096 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3097
a61af66fc99e Initial load
duke
parents:
diff changeset
3098 #endif //PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3099
a61af66fc99e Initial load
duke
parents:
diff changeset
3100
a61af66fc99e Initial load
duke
parents:
diff changeset
3101 // ********** verification functions for allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
3102 // (check that all intervals have a correct register and that no registers are overwritten)
a61af66fc99e Initial load
duke
parents:
diff changeset
3103 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3104
a61af66fc99e Initial load
duke
parents:
diff changeset
3105 void LinearScan::verify() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3106 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying intervals ******************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3107 verify_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3108
a61af66fc99e Initial load
duke
parents:
diff changeset
3109 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that no oops are in fixed intervals ****************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3110 verify_no_oops_in_fixed_intervals();
a61af66fc99e Initial load
duke
parents:
diff changeset
3111
a61af66fc99e Initial load
duke
parents:
diff changeset
3112 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying that unpinned constants are not alive across block boundaries"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3113 verify_constants();
a61af66fc99e Initial load
duke
parents:
diff changeset
3114
a61af66fc99e Initial load
duke
parents:
diff changeset
3115 TRACE_LINEAR_SCAN(2, tty->print_cr("********* verifying register allocation ********************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3116 verify_registers();
a61af66fc99e Initial load
duke
parents:
diff changeset
3117
a61af66fc99e Initial load
duke
parents:
diff changeset
3118 TRACE_LINEAR_SCAN(2, tty->print_cr("********* no errors found **********************************************"));
a61af66fc99e Initial load
duke
parents:
diff changeset
3119 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3120
a61af66fc99e Initial load
duke
parents:
diff changeset
3121 void LinearScan::verify_intervals() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3122 int len = interval_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3123 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3124
a61af66fc99e Initial load
duke
parents:
diff changeset
3125 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3126 Interval* i1 = interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3127 if (i1 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3128
a61af66fc99e Initial load
duke
parents:
diff changeset
3129 i1->check_split_children();
a61af66fc99e Initial load
duke
parents:
diff changeset
3130
a61af66fc99e Initial load
duke
parents:
diff changeset
3131 if (i1->reg_num() != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3132 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
3133 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3135
a61af66fc99e Initial load
duke
parents:
diff changeset
3136 if (i1->reg_num() >= LIR_OprDesc::vreg_base && i1->type() == T_ILLEGAL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3137 tty->print_cr("Interval %d has no type assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3138 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3140
a61af66fc99e Initial load
duke
parents:
diff changeset
3141 if (i1->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3142 tty->print_cr("Interval %d has no register assigned", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3143 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3144 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3145
a61af66fc99e Initial load
duke
parents:
diff changeset
3146 if (i1->assigned_reg() == i1->assigned_regHi()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3147 tty->print_cr("Interval %d: low and high register equal", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3148 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3149 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3150
a61af66fc99e Initial load
duke
parents:
diff changeset
3151 if (!is_processed_reg_num(i1->assigned_reg())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3152 tty->print_cr("Can not have an Interval for an ignored register"); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3153 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3154 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3155
a61af66fc99e Initial load
duke
parents:
diff changeset
3156 if (i1->first() == Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3157 tty->print_cr("Interval %d has no Range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3158 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3160
a61af66fc99e Initial load
duke
parents:
diff changeset
3161 for (Range* r = i1->first(); r != Range::end(); r = r->next()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3162 if (r->from() >= r->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3163 tty->print_cr("Interval %d has zero length range", i1->reg_num()); i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3164 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3167
a61af66fc99e Initial load
duke
parents:
diff changeset
3168 for (int j = i + 1; j < len; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3169 Interval* i2 = interval_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3170 if (i2 == NULL) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3171
a61af66fc99e Initial load
duke
parents:
diff changeset
3172 // special intervals that are created in MoveResolver
a61af66fc99e Initial load
duke
parents:
diff changeset
3173 // -> ignore them because the range information has no meaning there
a61af66fc99e Initial load
duke
parents:
diff changeset
3174 if (i1->from() == 1 && i1->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3175 if (i2->from() == 1 && i2->to() == 2) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
3176
a61af66fc99e Initial load
duke
parents:
diff changeset
3177 int r1 = i1->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3178 int r1Hi = i1->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3179 int r2 = i2->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3180 int r2Hi = i2->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3181 if (i1->intersects(i2) && (r1 == r2 || r1 == r2Hi || (r1Hi != any_reg && (r1Hi == r2 || r1Hi == r2Hi)))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3182 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
3183 i1->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3184 i2->print(); tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3185 has_error = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3189
a61af66fc99e Initial load
duke
parents:
diff changeset
3190 assert(has_error == false, "register allocation invalid");
a61af66fc99e Initial load
duke
parents:
diff changeset
3191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3192
a61af66fc99e Initial load
duke
parents:
diff changeset
3193
a61af66fc99e Initial load
duke
parents:
diff changeset
3194 void LinearScan::verify_no_oops_in_fixed_intervals() {
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3195 Interval* fixed_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3196 Interval* other_intervals;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3197 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
3198
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3199 // 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
3200 // with a high operation id
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3201 other_intervals = new Interval(any_reg);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3202 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
3203 IntervalWalker* iw = new IntervalWalker(this, fixed_intervals, other_intervals);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3204
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3205 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3206 for (int i = 0; i < block_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3207 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3208
a61af66fc99e Initial load
duke
parents:
diff changeset
3209 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
3210
a61af66fc99e Initial load
duke
parents:
diff changeset
3211 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3212 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3213 int op_id = op->id();
a61af66fc99e Initial load
duke
parents:
diff changeset
3214
a61af66fc99e Initial load
duke
parents:
diff changeset
3215 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3216
722
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3217 if (visitor.info_count() > 0) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3218 iw->walk_before(op->id());
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3219 bool check_live = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3220 if (op->code() == lir_move) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3221 LIR_Op1* move = (LIR_Op1*)op;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3222 check_live = (move->patch_code() == lir_patch_none);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3223 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3224 LIR_OpBranch* branch = op->as_OpBranch();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3225 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
3226 // 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
3227 // exception stub will never return to normal control flow.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3228 check_live = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3229 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3230
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3231 // 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
3232 // oopmap since we can't handle that correctly.
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3233 if (check_live) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3234 for (Interval* interval = iw->active_first(fixedKind);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3235 interval != Interval::end();
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3236 interval = interval->next()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3237 if (interval->current_to() > op->id() + 1) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3238 // 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
3239 // that this interval represents some value that's
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3240 // 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
3241 bool ok = false;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3242 for_each_visitor_mode(mode) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3243 int n = visitor.opr_count(mode);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3244 for (int k = 0; k < n; k++) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3245 LIR_Opr opr = visitor.opr_at(mode, k);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3246 if (opr->is_fixed_cpu()) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3247 if (interval_at(reg_num(opr)) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3248 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3249 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3250 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3251 int hi = reg_numHi(opr);
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3252 if (hi != -1 && interval_at(hi) == interval) {
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3253 ok = true;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3254 break;
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3255 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3256 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3257 }
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 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
3260 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3261 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3262 }
a134d9824964 6828024: verification of fixed interval usage is too weak
never
parents: 337
diff changeset
3263 }
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 // oop-maps at calls do not contain registers, so check is not needed
a61af66fc99e Initial load
duke
parents:
diff changeset
3266 if (!visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3267
a61af66fc99e Initial load
duke
parents:
diff changeset
3268 for_each_visitor_mode(mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3269 int n = visitor.opr_count(mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3270 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3271 LIR_Opr opr = visitor.opr_at(mode, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
3272
a61af66fc99e Initial load
duke
parents:
diff changeset
3273 if (opr->is_fixed_cpu() && opr->is_oop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3274 // operand is a non-virtual cpu register and contains an oop
a61af66fc99e Initial load
duke
parents:
diff changeset
3275 TRACE_LINEAR_SCAN(4, op->print_on(tty); tty->print("checking operand "); opr->print(); tty->cr());
a61af66fc99e Initial load
duke
parents:
diff changeset
3276
a61af66fc99e Initial load
duke
parents:
diff changeset
3277 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3278 assert(interval != NULL, "no interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
3279
a61af66fc99e Initial load
duke
parents:
diff changeset
3280 if (mode == LIR_OpVisitState::inputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3281 if (interval->to() >= op_id + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3282 assert(interval->to() < op_id + 2 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
3283 interval->has_hole_between(op_id, op_id + 2),
a61af66fc99e Initial load
duke
parents:
diff changeset
3284 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3285 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3286 } else if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3287 if (interval->from() <= op_id - 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3288 assert(interval->has_hole_between(op_id - 1, op_id),
a61af66fc99e Initial load
duke
parents:
diff changeset
3289 "oop input operand live after instruction");
a61af66fc99e Initial load
duke
parents:
diff changeset
3290 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3291 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3292 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3293 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3295 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3296 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3297 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3298 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3299
a61af66fc99e Initial load
duke
parents:
diff changeset
3300
a61af66fc99e Initial load
duke
parents:
diff changeset
3301 void LinearScan::verify_constants() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3302 int num_regs = num_virtual_regs();
a61af66fc99e Initial load
duke
parents:
diff changeset
3303 int size = live_set_size();
a61af66fc99e Initial load
duke
parents:
diff changeset
3304 int num_blocks = block_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
3305
a61af66fc99e Initial load
duke
parents:
diff changeset
3306 for (int i = 0; i < num_blocks; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3307 BlockBegin* block = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3308 BitMap live_at_edge = block->live_in();
a61af66fc99e Initial load
duke
parents:
diff changeset
3309
a61af66fc99e Initial load
duke
parents:
diff changeset
3310 // 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
3311 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
3312 TRACE_LINEAR_SCAN(4, tty->print("checking interval %d of block B%d", r, block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3313
a61af66fc99e Initial load
duke
parents:
diff changeset
3314 Value value = gen()->instruction_for_vreg(r);
a61af66fc99e Initial load
duke
parents:
diff changeset
3315
a61af66fc99e Initial load
duke
parents:
diff changeset
3316 assert(value != NULL, "all intervals live across block boundaries must have Value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3317 assert(value->operand()->is_register() && value->operand()->is_virtual(), "value must have virtual operand");
a61af66fc99e Initial load
duke
parents:
diff changeset
3318 assert(value->operand()->vreg_number() == r, "register number must match");
a61af66fc99e Initial load
duke
parents:
diff changeset
3319 // 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
3320 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3321 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3322 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3323
a61af66fc99e Initial load
duke
parents:
diff changeset
3324
a61af66fc99e Initial load
duke
parents:
diff changeset
3325 class RegisterVerifier: public StackObj {
a61af66fc99e Initial load
duke
parents:
diff changeset
3326 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
3327 LinearScan* _allocator;
a61af66fc99e Initial load
duke
parents:
diff changeset
3328 BlockList _work_list; // all blocks that must be processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3329 IntervalsList _saved_states; // saved information of previous check
a61af66fc99e Initial load
duke
parents:
diff changeset
3330
a61af66fc99e Initial load
duke
parents:
diff changeset
3331 // simplified access to methods of LinearScan
a61af66fc99e Initial load
duke
parents:
diff changeset
3332 Compilation* compilation() const { return _allocator->compilation(); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3333 Interval* interval_at(int reg_num) const { return _allocator->interval_at(reg_num); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3334 int reg_num(LIR_Opr opr) const { return _allocator->reg_num(opr); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3335
a61af66fc99e Initial load
duke
parents:
diff changeset
3336 // currently, only registers are processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3337 int state_size() { return LinearScan::nof_regs; }
a61af66fc99e Initial load
duke
parents:
diff changeset
3338
a61af66fc99e Initial load
duke
parents:
diff changeset
3339 // accessors
a61af66fc99e Initial load
duke
parents:
diff changeset
3340 IntervalList* state_for_block(BlockBegin* block) { return _saved_states.at(block->block_id()); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3341 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
3342 void add_to_work_list(BlockBegin* block) { if (!_work_list.contains(block)) _work_list.append(block); }
a61af66fc99e Initial load
duke
parents:
diff changeset
3343
a61af66fc99e Initial load
duke
parents:
diff changeset
3344 // helper functions
a61af66fc99e Initial load
duke
parents:
diff changeset
3345 IntervalList* copy(IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3346 void state_put(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3347 bool check_state(IntervalList* input_state, int reg, Interval* interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3348
a61af66fc99e Initial load
duke
parents:
diff changeset
3349 void process_block(BlockBegin* block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3350 void process_xhandler(XHandler* xhandler, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3351 void process_successor(BlockBegin* block, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3352 void process_operations(LIR_List* ops, IntervalList* input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3353
a61af66fc99e Initial load
duke
parents:
diff changeset
3354 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
3355 RegisterVerifier(LinearScan* allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3356 : _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
3357 , _work_list(16)
a61af66fc99e Initial load
duke
parents:
diff changeset
3358 , _saved_states(BlockBegin::number_of_blocks(), NULL)
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 verify(BlockBegin* start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3362 };
a61af66fc99e Initial load
duke
parents:
diff changeset
3363
a61af66fc99e Initial load
duke
parents:
diff changeset
3364
a61af66fc99e Initial load
duke
parents:
diff changeset
3365 // entry function from LinearScan that starts the verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3366 void LinearScan::verify_registers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3367 RegisterVerifier verifier(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
3368 verifier.verify(block_at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
3369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3370
a61af66fc99e Initial load
duke
parents:
diff changeset
3371
a61af66fc99e Initial load
duke
parents:
diff changeset
3372 void RegisterVerifier::verify(BlockBegin* start) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3373 // setup input registers (method arguments) for first block
a61af66fc99e Initial load
duke
parents:
diff changeset
3374 IntervalList* input_state = new IntervalList(state_size(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3375 CallingConvention* args = compilation()->frame_map()->incoming_arguments();
a61af66fc99e Initial load
duke
parents:
diff changeset
3376 for (int n = 0; n < args->length(); n++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3377 LIR_Opr opr = args->at(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
3378 if (opr->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3379 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3380
a61af66fc99e Initial load
duke
parents:
diff changeset
3381 if (interval->assigned_reg() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3382 input_state->at_put(interval->assigned_reg(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3383 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3384 if (interval->assigned_regHi() != LinearScan::any_reg && interval->assigned_regHi() < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3385 input_state->at_put(interval->assigned_regHi(), interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3387 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3389
a61af66fc99e Initial load
duke
parents:
diff changeset
3390 set_state_for_block(start, input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3391 add_to_work_list(start);
a61af66fc99e Initial load
duke
parents:
diff changeset
3392
a61af66fc99e Initial load
duke
parents:
diff changeset
3393 // main loop for verification
a61af66fc99e Initial load
duke
parents:
diff changeset
3394 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
3395 BlockBegin* block = _work_list.at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3396 _work_list.remove_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
3397
a61af66fc99e Initial load
duke
parents:
diff changeset
3398 process_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3399 } while (!_work_list.is_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3400 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3401
a61af66fc99e Initial load
duke
parents:
diff changeset
3402 void RegisterVerifier::process_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3403 TRACE_LINEAR_SCAN(2, tty->cr(); tty->print_cr("process_block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3404
a61af66fc99e Initial load
duke
parents:
diff changeset
3405 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3406 IntervalList* input_state = copy(state_for_block(block));
a61af66fc99e Initial load
duke
parents:
diff changeset
3407
a61af66fc99e Initial load
duke
parents:
diff changeset
3408 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3409 tty->print_cr("Input-State of intervals:");
a61af66fc99e Initial load
duke
parents:
diff changeset
3410 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
3411 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3412 if (input_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3413 tty->print(" %4d", input_state->at(i)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
3414 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3415 tty->print(" __");
a61af66fc99e Initial load
duke
parents:
diff changeset
3416 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3418 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3419 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
3420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3421
a61af66fc99e Initial load
duke
parents:
diff changeset
3422 // process all operations of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3423 process_operations(block->lir(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3424
a61af66fc99e Initial load
duke
parents:
diff changeset
3425 // iterate all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
3426 for (int i = 0; i < block->number_of_sux(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3427 process_successor(block->sux_at(i), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3429 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3430
a61af66fc99e Initial load
duke
parents:
diff changeset
3431 void RegisterVerifier::process_xhandler(XHandler* xhandler, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3432 TRACE_LINEAR_SCAN(2, tty->print_cr("process_xhandler B%d", xhandler->entry_block()->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3433
a61af66fc99e Initial load
duke
parents:
diff changeset
3434 // must copy state because it is modified
a61af66fc99e Initial load
duke
parents:
diff changeset
3435 input_state = copy(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3436
a61af66fc99e Initial load
duke
parents:
diff changeset
3437 if (xhandler->entry_code() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3438 process_operations(xhandler->entry_code(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3439 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3440 process_successor(xhandler->entry_block(), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3441 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3442
a61af66fc99e Initial load
duke
parents:
diff changeset
3443 void RegisterVerifier::process_successor(BlockBegin* block, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3444 IntervalList* saved_state = state_for_block(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3445
a61af66fc99e Initial load
duke
parents:
diff changeset
3446 if (saved_state != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3447 // this block was already processed before.
a61af66fc99e Initial load
duke
parents:
diff changeset
3448 // check if new input_state is consistent with saved_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3449
a61af66fc99e Initial load
duke
parents:
diff changeset
3450 bool saved_state_correct = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3451 for (int i = 0; i < state_size(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3452 if (input_state->at(i) != saved_state->at(i)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3453 // current input_state and previous saved_state assume a different
a61af66fc99e Initial load
duke
parents:
diff changeset
3454 // interval in this register -> assume that this register is invalid
a61af66fc99e Initial load
duke
parents:
diff changeset
3455 if (saved_state->at(i) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3456 // invalidate old calculation only if it assumed that
a61af66fc99e Initial load
duke
parents:
diff changeset
3457 // register was valid. when the register was already invalid,
a61af66fc99e Initial load
duke
parents:
diff changeset
3458 // then the old calculation was correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
3459 saved_state_correct = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3460 saved_state->at_put(i, NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3461
a61af66fc99e Initial load
duke
parents:
diff changeset
3462 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
3463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3464 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3466
a61af66fc99e Initial load
duke
parents:
diff changeset
3467 if (saved_state_correct) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3468 // already processed block with correct input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3469 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
3470 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3471 // must re-visit this block
a61af66fc99e Initial load
duke
parents:
diff changeset
3472 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
3473 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3474 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3475
a61af66fc99e Initial load
duke
parents:
diff changeset
3476 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3477 // block was not processed before, so set initial input_state
a61af66fc99e Initial load
duke
parents:
diff changeset
3478 TRACE_LINEAR_SCAN(2, tty->print_cr("process_successor B%d: initial visit", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3479
a61af66fc99e Initial load
duke
parents:
diff changeset
3480 set_state_for_block(block, copy(input_state));
a61af66fc99e Initial load
duke
parents:
diff changeset
3481 add_to_work_list(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
3482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3483 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3484
a61af66fc99e Initial load
duke
parents:
diff changeset
3485
a61af66fc99e Initial load
duke
parents:
diff changeset
3486 IntervalList* RegisterVerifier::copy(IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3487 IntervalList* copy_state = new IntervalList(input_state->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
3488 copy_state->push_all(input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3489 return copy_state;
a61af66fc99e Initial load
duke
parents:
diff changeset
3490 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3491
a61af66fc99e Initial load
duke
parents:
diff changeset
3492 void RegisterVerifier::state_put(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3493 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3494 if (interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3495 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = %d", reg, interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3496 } else if (input_state->at(reg) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3497 TRACE_LINEAR_SCAN(4, tty->print_cr(" reg[%d] = NULL", reg));
a61af66fc99e Initial load
duke
parents:
diff changeset
3498 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3499
a61af66fc99e Initial load
duke
parents:
diff changeset
3500 input_state->at_put(reg, interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3502 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3503
a61af66fc99e Initial load
duke
parents:
diff changeset
3504 bool RegisterVerifier::check_state(IntervalList* input_state, int reg, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3505 if (reg != LinearScan::any_reg && reg < state_size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3506 if (input_state->at(reg) != interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3507 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
3508 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3509 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3511 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3513
a61af66fc99e Initial load
duke
parents:
diff changeset
3514 void RegisterVerifier::process_operations(LIR_List* ops, IntervalList* input_state) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3515 // visit all instructions of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
3516 LIR_OpVisitState visitor;
a61af66fc99e Initial load
duke
parents:
diff changeset
3517 bool has_error = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3518
a61af66fc99e Initial load
duke
parents:
diff changeset
3519 for (int i = 0; i < ops->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3520 LIR_Op* op = ops->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3521 visitor.visit(op);
a61af66fc99e Initial load
duke
parents:
diff changeset
3522
a61af66fc99e Initial load
duke
parents:
diff changeset
3523 TRACE_LINEAR_SCAN(4, op->print_on(tty));
a61af66fc99e Initial load
duke
parents:
diff changeset
3524
a61af66fc99e Initial load
duke
parents:
diff changeset
3525 // check if input operands are correct
a61af66fc99e Initial load
duke
parents:
diff changeset
3526 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3527 int n = visitor.opr_count(LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3528 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3529 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::inputMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3530 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3531 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3532 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3533 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3534 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3535
a61af66fc99e Initial load
duke
parents:
diff changeset
3536 has_error |= check_state(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3537 has_error |= check_state(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3538
a61af66fc99e Initial load
duke
parents:
diff changeset
3539 // When an operand is marked with is_last_use, then the fpu stack allocator
a61af66fc99e Initial load
duke
parents:
diff changeset
3540 // removes the register from the fpu stack -> the register contains no value
a61af66fc99e Initial load
duke
parents:
diff changeset
3541 if (opr->is_last_use()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3542 state_put(input_state, interval->assigned_reg(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3543 state_put(input_state, interval->assigned_regHi(), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3546 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3547
a61af66fc99e Initial load
duke
parents:
diff changeset
3548 // invalidate all caller save registers at calls
a61af66fc99e Initial load
duke
parents:
diff changeset
3549 if (visitor.has_call()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3550 for (j = 0; j < FrameMap::nof_caller_save_cpu_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3551 state_put(input_state, reg_num(FrameMap::caller_save_cpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3552 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3553 for (j = 0; j < FrameMap::nof_caller_save_fpu_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3554 state_put(input_state, reg_num(FrameMap::caller_save_fpu_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3556
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
3557 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3558 for (j = 0; j < FrameMap::nof_caller_save_xmm_regs; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3559 state_put(input_state, reg_num(FrameMap::caller_save_xmm_reg_at(j)), NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3560 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3561 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3563
a61af66fc99e Initial load
duke
parents:
diff changeset
3564 // process xhandler before output and temp operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3565 XHandlers* xhandlers = visitor.all_xhandler();
a61af66fc99e Initial load
duke
parents:
diff changeset
3566 n = xhandlers->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
3567 for (int k = 0; k < n; k++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3568 process_xhandler(xhandlers->handler_at(k), input_state);
a61af66fc99e Initial load
duke
parents:
diff changeset
3569 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3570
a61af66fc99e Initial load
duke
parents:
diff changeset
3571 // 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
3572 n = visitor.opr_count(LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3573 for (j = 0; j < n; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3574 LIR_Opr opr = visitor.opr_at(LIR_OpVisitState::tempMode, j);
a61af66fc99e Initial load
duke
parents:
diff changeset
3575 if (opr->is_register() && LinearScan::is_processed_reg_num(reg_num(opr))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3576 Interval* interval = interval_at(reg_num(opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
3577 if (op->id() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3578 interval = interval->split_child_at_op_id(op->id(), LIR_OpVisitState::tempMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3579 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3580
a61af66fc99e Initial load
duke
parents:
diff changeset
3581 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3582 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3583 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3584 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3585
a61af66fc99e Initial load
duke
parents:
diff changeset
3586 // set output operands
a61af66fc99e Initial load
duke
parents:
diff changeset
3587 n = visitor.opr_count(LIR_OpVisitState::outputMode);
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::outputMode, 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::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
3594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3595
a61af66fc99e Initial load
duke
parents:
diff changeset
3596 state_put(input_state, interval->assigned_reg(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3597 state_put(input_state, interval->assigned_regHi(), interval->split_parent());
a61af66fc99e Initial load
duke
parents:
diff changeset
3598 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3599 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3601 assert(has_error == false, "Error in register allocation");
a61af66fc99e Initial load
duke
parents:
diff changeset
3602 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3603
a61af66fc99e Initial load
duke
parents:
diff changeset
3604 #endif // ASSERT
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 // **** Implementation of MoveResolver ******************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3609
a61af66fc99e Initial load
duke
parents:
diff changeset
3610 MoveResolver::MoveResolver(LinearScan* allocator) :
a61af66fc99e Initial load
duke
parents:
diff changeset
3611 _allocator(allocator),
a61af66fc99e Initial load
duke
parents:
diff changeset
3612 _multiple_reads_allowed(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
3613 _mapping_from(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3614 _mapping_from_opr(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3615 _mapping_to(8),
a61af66fc99e Initial load
duke
parents:
diff changeset
3616 _insert_list(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
3617 _insert_idx(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
3618 _insertion_buffer()
a61af66fc99e Initial load
duke
parents:
diff changeset
3619 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3620 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3621 _register_blocked[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
3622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3623 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3624 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3625
a61af66fc99e Initial load
duke
parents:
diff changeset
3626
a61af66fc99e Initial load
duke
parents:
diff changeset
3627 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3628
a61af66fc99e Initial load
duke
parents:
diff changeset
3629 void MoveResolver::check_empty() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3630 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
3631 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3632 assert(register_blocked(i) == 0, "register map must be empty before and after processing");
a61af66fc99e Initial load
duke
parents:
diff changeset
3633 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3634 assert(_multiple_reads_allowed == false, "must have default value");
a61af66fc99e Initial load
duke
parents:
diff changeset
3635 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3636
a61af66fc99e Initial load
duke
parents:
diff changeset
3637 void MoveResolver::verify_before_resolve() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3638 assert(_mapping_from.length() == _mapping_from_opr.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3639 assert(_mapping_from.length() == _mapping_to.length(), "length must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3640 assert(_insert_list != NULL && _insert_idx != -1, "insert position not set");
a61af66fc99e Initial load
duke
parents:
diff changeset
3641
a61af66fc99e Initial load
duke
parents:
diff changeset
3642 int i, j;
a61af66fc99e Initial load
duke
parents:
diff changeset
3643 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3644 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3645 for (j = i + 1; j < _mapping_from.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3646 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
3647 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3649 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3650
a61af66fc99e Initial load
duke
parents:
diff changeset
3651 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3652 for (j = i + 1; j < _mapping_to.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3653 assert(_mapping_to.at(i) != _mapping_to.at(j), "cannot write to same interval twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3655 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3656
a61af66fc99e Initial load
duke
parents:
diff changeset
3657
a61af66fc99e Initial load
duke
parents:
diff changeset
3658 BitMap used_regs(LinearScan::nof_regs + allocator()->frame_map()->argcount() + allocator()->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
3659 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3660 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3661 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3662 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3663 if (it != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3664 assert(!used_regs.at(it->assigned_reg()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3665 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3666
a61af66fc99e Initial load
duke
parents:
diff changeset
3667 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3668 assert(!used_regs.at(it->assigned_regHi()), "cannot read from same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3669 used_regs.set_bit(it->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
3670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3671 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3672 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3673 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3674
a61af66fc99e Initial load
duke
parents:
diff changeset
3675 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3676 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3677 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3678 assert(!used_regs.at(it->assigned_reg()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3679 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3680
a61af66fc99e Initial load
duke
parents:
diff changeset
3681 if (it->assigned_regHi() != LinearScan::any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3682 assert(!used_regs.at(it->assigned_regHi()), "cannot write to same register twice");
a61af66fc99e Initial load
duke
parents:
diff changeset
3683 used_regs.set_bit(it->assigned_regHi());
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 used_regs.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
3688 for (i = 0; i < _mapping_from.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3689 Interval* it = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3690 if (it != NULL && it->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3691 used_regs.set_bit(it->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
3692 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3693 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3694 for (i = 0; i < _mapping_to.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3695 Interval* it = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3696 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
3697 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3698 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3699
a61af66fc99e Initial load
duke
parents:
diff changeset
3700 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
3701
a61af66fc99e Initial load
duke
parents:
diff changeset
3702
a61af66fc99e Initial load
duke
parents:
diff changeset
3703 // mark assigned_reg and assigned_regHi of the interval as blocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3704 void MoveResolver::block_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3705 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3706 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3707 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3708 set_register_blocked(reg, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3709 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3710 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3711 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3712 assert(_multiple_reads_allowed || register_blocked(reg) == 0, "register already marked as used");
a61af66fc99e Initial load
duke
parents:
diff changeset
3713 set_register_blocked(reg, 1);
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 // mark assigned_reg and assigned_regHi of the interval as unblocked
a61af66fc99e Initial load
duke
parents:
diff changeset
3718 void MoveResolver::unblock_registers(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3719 int reg = it->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3720 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3721 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3722 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3723 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3724 reg = it->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3725 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3726 assert(register_blocked(reg) > 0, "register already marked as unused");
a61af66fc99e Initial load
duke
parents:
diff changeset
3727 set_register_blocked(reg, -1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3728 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3729 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3730
a61af66fc99e Initial load
duke
parents:
diff changeset
3731 // 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
3732 bool MoveResolver::save_to_process_move(Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3733 int from_reg = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3734 int from_regHi = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3735 if (from != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3736 from_reg = from->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3737 from_regHi = from->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3738 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3739
a61af66fc99e Initial load
duke
parents:
diff changeset
3740 int reg = to->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
3741 if (reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3742 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3743 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3744 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3745 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3746 reg = to->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
3747 if (reg != LinearScan::any_reg && reg < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3748 if (register_blocked(reg) > 1 || (register_blocked(reg) == 1 && reg != from_reg && reg != from_regHi)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3749 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3750 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3751 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3752
a61af66fc99e Initial load
duke
parents:
diff changeset
3753 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3754 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3755
a61af66fc99e Initial load
duke
parents:
diff changeset
3756
a61af66fc99e Initial load
duke
parents:
diff changeset
3757 void MoveResolver::create_insertion_buffer(LIR_List* list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3758 assert(!_insertion_buffer.initialized(), "overwriting existing buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3759 _insertion_buffer.init(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3760 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3761
a61af66fc99e Initial load
duke
parents:
diff changeset
3762 void MoveResolver::append_insertion_buffer() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3763 if (_insertion_buffer.initialized()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3764 _insertion_buffer.lir_list()->append(&_insertion_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
3765 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3766 assert(!_insertion_buffer.initialized(), "must be uninitialized now");
a61af66fc99e Initial load
duke
parents:
diff changeset
3767
a61af66fc99e Initial load
duke
parents:
diff changeset
3768 _insert_list = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
3769 _insert_idx = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3770 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3771
a61af66fc99e Initial load
duke
parents:
diff changeset
3772 void MoveResolver::insert_move(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3773 assert(from_interval->reg_num() != to_interval->reg_num(), "from and to interval equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
3774 assert(from_interval->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3775 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3776 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3777
a61af66fc99e Initial load
duke
parents:
diff changeset
3778 LIR_Opr from_opr = LIR_OprFact::virtual_register(from_interval->reg_num(), from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3779 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3780
a61af66fc99e Initial load
duke
parents:
diff changeset
3781 if (!_multiple_reads_allowed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3782 // the last_use flag is an optimization for FPU stack allocation. When the same
a61af66fc99e Initial load
duke
parents:
diff changeset
3783 // input interval is used in more than one move, then it is too difficult to determine
a61af66fc99e Initial load
duke
parents:
diff changeset
3784 // if this move is really the last use.
a61af66fc99e Initial load
duke
parents:
diff changeset
3785 from_opr = from_opr->make_last_use();
a61af66fc99e Initial load
duke
parents:
diff changeset
3786 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3787 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3788
a61af66fc99e Initial load
duke
parents:
diff changeset
3789 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
3790 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3791
a61af66fc99e Initial load
duke
parents:
diff changeset
3792 void MoveResolver::insert_move(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3793 assert(from_opr->type() == to_interval->type(), "move between different types");
a61af66fc99e Initial load
duke
parents:
diff changeset
3794 assert(_insert_list != NULL && _insert_idx != -1, "must setup insert position first");
a61af66fc99e Initial load
duke
parents:
diff changeset
3795 assert(_insertion_buffer.lir_list() == _insert_list, "wrong insertion buffer");
a61af66fc99e Initial load
duke
parents:
diff changeset
3796
a61af66fc99e Initial load
duke
parents:
diff changeset
3797 LIR_Opr to_opr = LIR_OprFact::virtual_register(to_interval->reg_num(), to_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3798 _insertion_buffer.move(_insert_idx, from_opr, to_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3799
a61af66fc99e Initial load
duke
parents:
diff changeset
3800 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
3801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3802
a61af66fc99e Initial load
duke
parents:
diff changeset
3803
a61af66fc99e Initial load
duke
parents:
diff changeset
3804 void MoveResolver::resolve_mappings() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3805 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
3806 DEBUG_ONLY(verify_before_resolve());
a61af66fc99e Initial load
duke
parents:
diff changeset
3807
a61af66fc99e Initial load
duke
parents:
diff changeset
3808 // Block all registers that are used as input operands of a move.
a61af66fc99e Initial load
duke
parents:
diff changeset
3809 // When a register is blocked, no move to this register is emitted.
a61af66fc99e Initial load
duke
parents:
diff changeset
3810 // This is necessary for detecting cycles in moves.
a61af66fc99e Initial load
duke
parents:
diff changeset
3811 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3812 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3813 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3814 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3815 block_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3816 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3817 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3818
a61af66fc99e Initial load
duke
parents:
diff changeset
3819 int spill_candidate = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3820 while (_mapping_from.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3821 bool processed_interval = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3822
a61af66fc99e Initial load
duke
parents:
diff changeset
3823 for (i = _mapping_from.length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3824 Interval* from_interval = _mapping_from.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3825 Interval* to_interval = _mapping_to.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3826
a61af66fc99e Initial load
duke
parents:
diff changeset
3827 if (save_to_process_move(from_interval, to_interval)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3828 // this inverval can be processed because target is free
a61af66fc99e Initial load
duke
parents:
diff changeset
3829 if (from_interval != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3830 insert_move(from_interval, to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3831 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3832 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3833 insert_move(_mapping_from_opr.at(i), to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3834 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3835 _mapping_from.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3836 _mapping_from_opr.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3837 _mapping_to.remove_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
3838
a61af66fc99e Initial load
duke
parents:
diff changeset
3839 processed_interval = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
3840 } else if (from_interval != NULL && from_interval->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3841 // this interval cannot be processed now because target is not free
a61af66fc99e Initial load
duke
parents:
diff changeset
3842 // it starts in a register, so it is a possible candidate for spilling
a61af66fc99e Initial load
duke
parents:
diff changeset
3843 spill_candidate = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
3844 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3845 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3846
a61af66fc99e Initial load
duke
parents:
diff changeset
3847 if (!processed_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3848 // no move could be processed because there is a cycle in the move list
a61af66fc99e Initial load
duke
parents:
diff changeset
3849 // (e.g. r1 -> r2, r2 -> r1), so one interval must be spilled to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
3850 assert(spill_candidate != -1, "no interval in register for spilling found");
a61af66fc99e Initial load
duke
parents:
diff changeset
3851
a61af66fc99e Initial load
duke
parents:
diff changeset
3852 // create a new spill interval and assign a stack slot to it
a61af66fc99e Initial load
duke
parents:
diff changeset
3853 Interval* from_interval = _mapping_from.at(spill_candidate);
a61af66fc99e Initial load
duke
parents:
diff changeset
3854 Interval* spill_interval = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
3855 spill_interval->set_type(from_interval->type());
a61af66fc99e Initial load
duke
parents:
diff changeset
3856
a61af66fc99e Initial load
duke
parents:
diff changeset
3857 // add a dummy range because real position is difficult to calculate
a61af66fc99e Initial load
duke
parents:
diff changeset
3858 // Note: this range is a special case when the integrity of the allocation is checked
a61af66fc99e Initial load
duke
parents:
diff changeset
3859 spill_interval->add_range(1, 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3860
a61af66fc99e Initial load
duke
parents:
diff changeset
3861 // do not allocate a new spill slot for temporary interval, but
a61af66fc99e Initial load
duke
parents:
diff changeset
3862 // use spill slot assigned to from_interval. Otherwise moves from
a61af66fc99e Initial load
duke
parents:
diff changeset
3863 // one stack slot to another can happen (not allowed by LIR_Assembler
a61af66fc99e Initial load
duke
parents:
diff changeset
3864 int spill_slot = from_interval->canonical_spill_slot();
a61af66fc99e Initial load
duke
parents:
diff changeset
3865 if (spill_slot < 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3866 spill_slot = allocator()->allocate_spill_slot(type2spill_size[spill_interval->type()] == 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
3867 from_interval->set_canonical_spill_slot(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3868 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3869 spill_interval->assign_reg(spill_slot);
a61af66fc99e Initial load
duke
parents:
diff changeset
3870 allocator()->append_interval(spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3871
a61af66fc99e Initial load
duke
parents:
diff changeset
3872 TRACE_LINEAR_SCAN(4, tty->print_cr("created new Interval %d for spilling", spill_interval->reg_num()));
a61af66fc99e Initial load
duke
parents:
diff changeset
3873
a61af66fc99e Initial load
duke
parents:
diff changeset
3874 // insert a move from register to stack and update the mapping
a61af66fc99e Initial load
duke
parents:
diff changeset
3875 insert_move(from_interval, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3876 _mapping_from.at_put(spill_candidate, spill_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3877 unblock_registers(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3878 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3879 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3880
a61af66fc99e Initial load
duke
parents:
diff changeset
3881 // reset to default value
a61af66fc99e Initial load
duke
parents:
diff changeset
3882 _multiple_reads_allowed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
3883
a61af66fc99e Initial load
duke
parents:
diff changeset
3884 // check that all intervals have been processed
a61af66fc99e Initial load
duke
parents:
diff changeset
3885 DEBUG_ONLY(check_empty());
a61af66fc99e Initial load
duke
parents:
diff changeset
3886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3887
a61af66fc99e Initial load
duke
parents:
diff changeset
3888
a61af66fc99e Initial load
duke
parents:
diff changeset
3889 void MoveResolver::set_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3890 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
3891 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
3892
a61af66fc99e Initial load
duke
parents:
diff changeset
3893 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3894 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3895 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3897
a61af66fc99e Initial load
duke
parents:
diff changeset
3898 void MoveResolver::move_insert_position(LIR_List* insert_list, int insert_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3899 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
3900
a61af66fc99e Initial load
duke
parents:
diff changeset
3901 if (_insert_list != NULL && (insert_list != _insert_list || insert_idx != _insert_idx)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3902 // insert position changed -> resolve current mappings
a61af66fc99e Initial load
duke
parents:
diff changeset
3903 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3904 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3905
a61af66fc99e Initial load
duke
parents:
diff changeset
3906 if (insert_list != _insert_list) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3907 // block changed -> append insertion_buffer because it is
a61af66fc99e Initial load
duke
parents:
diff changeset
3908 // bound to a specific block and create a new insertion_buffer
a61af66fc99e Initial load
duke
parents:
diff changeset
3909 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
3910 create_insertion_buffer(insert_list);
a61af66fc99e Initial load
duke
parents:
diff changeset
3911 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3912
a61af66fc99e Initial load
duke
parents:
diff changeset
3913 _insert_list = insert_list;
a61af66fc99e Initial load
duke
parents:
diff changeset
3914 _insert_idx = insert_idx;
a61af66fc99e Initial load
duke
parents:
diff changeset
3915 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3916
a61af66fc99e Initial load
duke
parents:
diff changeset
3917 void MoveResolver::add_mapping(Interval* from_interval, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3918 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
3919
a61af66fc99e Initial load
duke
parents:
diff changeset
3920 _mapping_from.append(from_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3921 _mapping_from_opr.append(LIR_OprFact::illegalOpr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3922 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3923 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3924
a61af66fc99e Initial load
duke
parents:
diff changeset
3925
a61af66fc99e Initial load
duke
parents:
diff changeset
3926 void MoveResolver::add_mapping(LIR_Opr from_opr, Interval* to_interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3927 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
3928 assert(from_opr->is_constant(), "only for constants");
a61af66fc99e Initial load
duke
parents:
diff changeset
3929
a61af66fc99e Initial load
duke
parents:
diff changeset
3930 _mapping_from.append(NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
3931 _mapping_from_opr.append(from_opr);
a61af66fc99e Initial load
duke
parents:
diff changeset
3932 _mapping_to.append(to_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
3933 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3934
a61af66fc99e Initial load
duke
parents:
diff changeset
3935 void MoveResolver::resolve_and_append_moves() {
a61af66fc99e Initial load
duke
parents:
diff changeset
3936 if (has_mappings()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3937 resolve_mappings();
a61af66fc99e Initial load
duke
parents:
diff changeset
3938 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3939 append_insertion_buffer();
a61af66fc99e Initial load
duke
parents:
diff changeset
3940 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3941
a61af66fc99e Initial load
duke
parents:
diff changeset
3942
a61af66fc99e Initial load
duke
parents:
diff changeset
3943
a61af66fc99e Initial load
duke
parents:
diff changeset
3944 // **** Implementation of Range *************************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3945
a61af66fc99e Initial load
duke
parents:
diff changeset
3946 Range::Range(int from, int to, Range* next) :
a61af66fc99e Initial load
duke
parents:
diff changeset
3947 _from(from),
a61af66fc99e Initial load
duke
parents:
diff changeset
3948 _to(to),
a61af66fc99e Initial load
duke
parents:
diff changeset
3949 _next(next)
a61af66fc99e Initial load
duke
parents:
diff changeset
3950 {
a61af66fc99e Initial load
duke
parents:
diff changeset
3951 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3952
a61af66fc99e Initial load
duke
parents:
diff changeset
3953 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
3954 Range* Range::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
3955 void Range::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
3956 _end = new (arena) Range(max_jint, max_jint, NULL);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3958
a61af66fc99e Initial load
duke
parents:
diff changeset
3959 int Range::intersects_at(Range* r2) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
3960 const Range* r1 = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
3961
a61af66fc99e Initial load
duke
parents:
diff changeset
3962 assert(r1 != NULL && r2 != NULL, "null ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
3963 assert(r1 != _end && r2 != _end, "empty ranges not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
3964
a61af66fc99e Initial load
duke
parents:
diff changeset
3965 do {
a61af66fc99e Initial load
duke
parents:
diff changeset
3966 if (r1->from() < r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3967 if (r1->to() <= r2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3968 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3969 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3970 return r2->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
3971 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3972 } else if (r2->from() < r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3973 if (r2->to() <= r1->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3974 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3975 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3976 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
3977 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3978 } else { // r1->from() == r2->from()
a61af66fc99e Initial load
duke
parents:
diff changeset
3979 if (r1->from() == r1->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3980 r1 = r1->next(); if (r1 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3981 } else if (r2->from() == r2->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
3982 r2 = r2->next(); if (r2 == _end) return -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
3983 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
3984 return r1->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
3985 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3986 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3987 } while (true);
a61af66fc99e Initial load
duke
parents:
diff changeset
3988 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3989
a61af66fc99e Initial load
duke
parents:
diff changeset
3990 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
3991 void Range::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
3992 out->print("[%d, %d[ ", _from, _to);
a61af66fc99e Initial load
duke
parents:
diff changeset
3993 }
a61af66fc99e Initial load
duke
parents:
diff changeset
3994 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
3995
a61af66fc99e Initial load
duke
parents:
diff changeset
3996
a61af66fc99e Initial load
duke
parents:
diff changeset
3997
a61af66fc99e Initial load
duke
parents:
diff changeset
3998 // **** Implementation of Interval **********************************
a61af66fc99e Initial load
duke
parents:
diff changeset
3999
a61af66fc99e Initial load
duke
parents:
diff changeset
4000 // initialize sentinel
a61af66fc99e Initial load
duke
parents:
diff changeset
4001 Interval* Interval::_end = NULL;
1584
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4002 void Interval::initialize(Arena* arena) {
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4003 Range::initialize(arena);
b812ff5abc73 6958292: C1: Enable parallel compilation
iveresov
parents: 1552
diff changeset
4004 _end = new (arena) Interval(-1);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4005 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4006
a61af66fc99e Initial load
duke
parents:
diff changeset
4007 Interval::Interval(int reg_num) :
a61af66fc99e Initial load
duke
parents:
diff changeset
4008 _reg_num(reg_num),
a61af66fc99e Initial load
duke
parents:
diff changeset
4009 _type(T_ILLEGAL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4010 _first(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4011 _use_pos_and_kinds(12),
a61af66fc99e Initial load
duke
parents:
diff changeset
4012 _current(Range::end()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4013 _next(_end),
a61af66fc99e Initial load
duke
parents:
diff changeset
4014 _state(invalidState),
a61af66fc99e Initial load
duke
parents:
diff changeset
4015 _assigned_reg(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4016 _assigned_regHi(LinearScan::any_reg),
a61af66fc99e Initial load
duke
parents:
diff changeset
4017 _cached_to(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4018 _cached_opr(LIR_OprFact::illegalOpr),
a61af66fc99e Initial load
duke
parents:
diff changeset
4019 _cached_vm_reg(VMRegImpl::Bad()),
a61af66fc99e Initial load
duke
parents:
diff changeset
4020 _split_children(0),
a61af66fc99e Initial load
duke
parents:
diff changeset
4021 _canonical_spill_slot(-1),
a61af66fc99e Initial load
duke
parents:
diff changeset
4022 _insert_move_when_activated(false),
a61af66fc99e Initial load
duke
parents:
diff changeset
4023 _register_hint(NULL),
a61af66fc99e Initial load
duke
parents:
diff changeset
4024 _spill_state(noDefinitionFound),
a61af66fc99e Initial load
duke
parents:
diff changeset
4025 _spill_definition_pos(-1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4026 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4027 _split_parent = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4028 _current_split_child = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4029 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4030
a61af66fc99e Initial load
duke
parents:
diff changeset
4031 int Interval::calc_to() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4032 assert(_first != Range::end(), "interval has no range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4033
a61af66fc99e Initial load
duke
parents:
diff changeset
4034 Range* r = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4035 while (r->next() != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4036 r = r->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4038 return r->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4039 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4040
a61af66fc99e Initial load
duke
parents:
diff changeset
4041
a61af66fc99e Initial load
duke
parents:
diff changeset
4042 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4043 // consistency check of split-children
a61af66fc99e Initial load
duke
parents:
diff changeset
4044 void Interval::check_split_children() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4045 if (_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4046 assert(is_split_parent(), "only split parents can have children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4047
a61af66fc99e Initial load
duke
parents:
diff changeset
4048 for (int i = 0; i < _split_children.length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4049 Interval* i1 = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4050
a61af66fc99e Initial load
duke
parents:
diff changeset
4051 assert(i1->split_parent() == this, "not a split child of this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4052 assert(i1->type() == type(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4053 assert(i1->canonical_spill_slot() == canonical_spill_slot(), "must be equal for all split children");
a61af66fc99e Initial load
duke
parents:
diff changeset
4054
a61af66fc99e Initial load
duke
parents:
diff changeset
4055 for (int j = i + 1; j < _split_children.length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4056 Interval* i2 = _split_children.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
4057
a61af66fc99e Initial load
duke
parents:
diff changeset
4058 assert(i1->reg_num() != i2->reg_num(), "same register number");
a61af66fc99e Initial load
duke
parents:
diff changeset
4059
a61af66fc99e Initial load
duke
parents:
diff changeset
4060 if (i1->from() < i2->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4061 assert(i1->to() <= i2->from() && i1->to() < i2->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4062 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4063 assert(i2->from() < i1->from(), "intervals start at same op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4064 assert(i2->to() <= i1->from() && i2->to() < i1->to(), "intervals overlapping");
a61af66fc99e Initial load
duke
parents:
diff changeset
4065 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4066 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4067 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4068 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4069 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4070 #endif // ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4071
a61af66fc99e Initial load
duke
parents:
diff changeset
4072 Interval* Interval::register_hint(bool search_split_child) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4073 if (!search_split_child) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4074 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4075 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4076
a61af66fc99e Initial load
duke
parents:
diff changeset
4077 if (_register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4078 assert(_register_hint->is_split_parent(), "ony split parents are valid hint registers");
a61af66fc99e Initial load
duke
parents:
diff changeset
4079
a61af66fc99e Initial load
duke
parents:
diff changeset
4080 if (_register_hint->assigned_reg() >= 0 && _register_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4081 return _register_hint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4082
a61af66fc99e Initial load
duke
parents:
diff changeset
4083 } else if (_register_hint->_split_children.length() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4084 // search the first split child that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4085 int len = _register_hint->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4086 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4087 Interval* cur = _register_hint->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4088
a61af66fc99e Initial load
duke
parents:
diff changeset
4089 if (cur->assigned_reg() >= 0 && cur->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4090 return cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4091 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4092 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4093 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4094 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4095
a61af66fc99e Initial load
duke
parents:
diff changeset
4096 // no hint interval found that has a register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
4097 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4098 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4099
a61af66fc99e Initial load
duke
parents:
diff changeset
4100
a61af66fc99e Initial load
duke
parents:
diff changeset
4101 Interval* Interval::split_child_at_op_id(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4102 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4103 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4104
a61af66fc99e Initial load
duke
parents:
diff changeset
4105 Interval* result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4106 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4107 result = this;
a61af66fc99e Initial load
duke
parents:
diff changeset
4108 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4109 result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4110 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4111
a61af66fc99e Initial load
duke
parents:
diff changeset
4112 // in outputMode, the end of the interval (op_id == cur->to()) is not valid
a61af66fc99e Initial load
duke
parents:
diff changeset
4113 int to_offset = (mode == LIR_OpVisitState::outputMode ? 0 : 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4114
a61af66fc99e Initial load
duke
parents:
diff changeset
4115 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4116 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4117 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4118 if (cur->from() <= op_id && op_id < cur->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4119 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4120 // exchange current split child to start of list (faster access for next call)
a61af66fc99e Initial load
duke
parents:
diff changeset
4121 _split_children.at_put(i, _split_children.at(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
4122 _split_children.at_put(0, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4124
a61af66fc99e Initial load
duke
parents:
diff changeset
4125 // interval found
a61af66fc99e Initial load
duke
parents:
diff changeset
4126 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4127 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
4128 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4130
a61af66fc99e Initial load
duke
parents:
diff changeset
4131 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4132 for (i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4133 Interval* tmp = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4134 if (tmp != result && tmp->from() <= op_id && op_id < tmp->to() + to_offset) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4135 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
4136 result->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4137 tmp->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4138 assert(false, "two valid result intervals found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4141 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4143
a61af66fc99e Initial load
duke
parents:
diff changeset
4144 assert(result != NULL, "no matching interval found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4145 assert(result->covers(op_id, mode), "op_id not covered by interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4146
a61af66fc99e Initial load
duke
parents:
diff changeset
4147 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4149
a61af66fc99e Initial load
duke
parents:
diff changeset
4150
a61af66fc99e Initial load
duke
parents:
diff changeset
4151 // returns the last split child that ends before the given op_id
a61af66fc99e Initial load
duke
parents:
diff changeset
4152 Interval* Interval::split_child_before_op_id(int op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4153 assert(op_id >= 0, "invalid op_id");
a61af66fc99e Initial load
duke
parents:
diff changeset
4154
a61af66fc99e Initial load
duke
parents:
diff changeset
4155 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4156 Interval* result = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4157
a61af66fc99e Initial load
duke
parents:
diff changeset
4158 int len = parent->_split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4159 assert(len > 0, "no split children available");
a61af66fc99e Initial load
duke
parents:
diff changeset
4160
a61af66fc99e Initial load
duke
parents:
diff changeset
4161 for (int i = len - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4162 Interval* cur = parent->_split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4163 if (cur->to() <= op_id && (result == NULL || result->to() < cur->to())) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4164 result = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4165 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4166 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4167
a61af66fc99e Initial load
duke
parents:
diff changeset
4168 assert(result != NULL, "no split child found");
a61af66fc99e Initial load
duke
parents:
diff changeset
4169 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4171
a61af66fc99e Initial load
duke
parents:
diff changeset
4172
a61af66fc99e Initial load
duke
parents:
diff changeset
4173 // checks if op_id is covered by any split child
a61af66fc99e Initial load
duke
parents:
diff changeset
4174 bool Interval::split_child_covers(int op_id, LIR_OpVisitState::OprMode mode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4175 assert(is_split_parent(), "can only be called for split parents");
a61af66fc99e Initial load
duke
parents:
diff changeset
4176 assert(op_id >= 0, "invalid op_id (method can not be called for spill moves)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4177
a61af66fc99e Initial load
duke
parents:
diff changeset
4178 if (_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4179 // simple case if interval was not split
a61af66fc99e Initial load
duke
parents:
diff changeset
4180 return covers(op_id, mode);
a61af66fc99e Initial load
duke
parents:
diff changeset
4181
a61af66fc99e Initial load
duke
parents:
diff changeset
4182 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4183 // extended case: check all split children
a61af66fc99e Initial load
duke
parents:
diff changeset
4184 int len = _split_children.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4185 for (int i = 0; i < len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4186 Interval* cur = _split_children.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4187 if (cur->covers(op_id, mode)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4188 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4191 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4192 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4194
a61af66fc99e Initial load
duke
parents:
diff changeset
4195
a61af66fc99e Initial load
duke
parents:
diff changeset
4196 // Note: use positions are sorted descending -> first use has highest index
a61af66fc99e Initial load
duke
parents:
diff changeset
4197 int Interval::first_usage(IntervalUseKind min_use_kind) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4198 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4199
a61af66fc99e Initial load
duke
parents:
diff changeset
4200 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4201 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4202 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4203 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4205 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4206 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4207
a61af66fc99e Initial load
duke
parents:
diff changeset
4208 int Interval::next_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4209 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4210
a61af66fc99e Initial load
duke
parents:
diff changeset
4211 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4212 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
4213 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4215 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4216 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4217 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4218
a61af66fc99e Initial load
duke
parents:
diff changeset
4219 int Interval::next_usage_exact(IntervalUseKind exact_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4220 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4221
a61af66fc99e Initial load
duke
parents:
diff changeset
4222 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4223 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
4224 return _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4227 return max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4228 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4229
a61af66fc99e Initial load
duke
parents:
diff changeset
4230 int Interval::previous_usage(IntervalUseKind min_use_kind, int from) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4231 assert(LinearScan::is_virtual_interval(this), "cannot access use positions for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4232
a61af66fc99e Initial load
duke
parents:
diff changeset
4233 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4234 for (int i = _use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4235 if (_use_pos_and_kinds.at(i) > from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4236 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4238 if (_use_pos_and_kinds.at(i + 1) >= min_use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4239 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4242 return prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4244
a61af66fc99e Initial load
duke
parents:
diff changeset
4245 void Interval::add_use_pos(int pos, IntervalUseKind use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4246 assert(covers(pos, LIR_OpVisitState::inputMode), "use position not covered by live range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4247
a61af66fc99e Initial load
duke
parents:
diff changeset
4248 // do not add use positions for precolored intervals because
a61af66fc99e Initial load
duke
parents:
diff changeset
4249 // they are never used
a61af66fc99e Initial load
duke
parents:
diff changeset
4250 if (use_kind != noUse && reg_num() >= LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4251 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4252 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4253 for (int i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4254 assert(pos <= _use_pos_and_kinds.at(i), "already added a use-position with lower position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4255 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
4256 if (i > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4257 assert(_use_pos_and_kinds.at(i) < _use_pos_and_kinds.at(i - 2), "not sorted descending");
a61af66fc99e Initial load
duke
parents:
diff changeset
4258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4259 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4260 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4261
a61af66fc99e Initial load
duke
parents:
diff changeset
4262 // Note: add_use is called in descending order, so list gets sorted
a61af66fc99e Initial load
duke
parents:
diff changeset
4263 // automatically by just appending new use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4264 int len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4265 if (len == 0 || _use_pos_and_kinds.at(len - 2) > pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4266 _use_pos_and_kinds.append(pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4267 _use_pos_and_kinds.append(use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4268 } else if (_use_pos_and_kinds.at(len - 1) < use_kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4269 assert(_use_pos_and_kinds.at(len - 2) == pos, "list not sorted correctly");
a61af66fc99e Initial load
duke
parents:
diff changeset
4270 _use_pos_and_kinds.at_put(len - 1, use_kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4274
a61af66fc99e Initial load
duke
parents:
diff changeset
4275 void Interval::add_range(int from, int to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4276 assert(from < to, "invalid range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4277 assert(first() == Range::end() || to < first()->next()->from(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4278 assert(from <= first()->to(), "not inserting at begin of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4279
a61af66fc99e Initial load
duke
parents:
diff changeset
4280 if (first()->from() <= to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4281 // join intersecting ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4282 first()->set_from(MIN2(from, first()->from()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4283 first()->set_to (MAX2(to, first()->to()));
a61af66fc99e Initial load
duke
parents:
diff changeset
4284 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4285 // insert new range
a61af66fc99e Initial load
duke
parents:
diff changeset
4286 _first = new Range(from, to, first());
a61af66fc99e Initial load
duke
parents:
diff changeset
4287 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4288 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4289
a61af66fc99e Initial load
duke
parents:
diff changeset
4290 Interval* Interval::new_split_child() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4291 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4292 Interval* result = new Interval(-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4293 result->set_type(type());
a61af66fc99e Initial load
duke
parents:
diff changeset
4294
a61af66fc99e Initial load
duke
parents:
diff changeset
4295 Interval* parent = split_parent();
a61af66fc99e Initial load
duke
parents:
diff changeset
4296 result->_split_parent = parent;
a61af66fc99e Initial load
duke
parents:
diff changeset
4297 result->set_register_hint(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
4298
a61af66fc99e Initial load
duke
parents:
diff changeset
4299 // insert new interval in children-list of parent
a61af66fc99e Initial load
duke
parents:
diff changeset
4300 if (parent->_split_children.length() == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4301 assert(is_split_parent(), "list must be initialized at first split");
a61af66fc99e Initial load
duke
parents:
diff changeset
4302
a61af66fc99e Initial load
duke
parents:
diff changeset
4303 parent->_split_children = IntervalList(4);
a61af66fc99e Initial load
duke
parents:
diff changeset
4304 parent->_split_children.append(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4305 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4306 parent->_split_children.append(result);
a61af66fc99e Initial load
duke
parents:
diff changeset
4307
a61af66fc99e Initial load
duke
parents:
diff changeset
4308 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4309 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4310
a61af66fc99e Initial load
duke
parents:
diff changeset
4311 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4312 // the remainder as a new interval.
a61af66fc99e Initial load
duke
parents:
diff changeset
4313 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4314 // when an interval is split, a bi-directional link is established between the original interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4315 // (the split parent) and the intervals that are split off this interval (the split children)
a61af66fc99e Initial load
duke
parents:
diff changeset
4316 // When a split child is split again, the new created interval is also a direct child
a61af66fc99e Initial load
duke
parents:
diff changeset
4317 // of the original parent (there is no tree of split children stored, but a flat list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4318 // All split children are spilled to the same stack slot (stored in _canonical_spill_slot)
a61af66fc99e Initial load
duke
parents:
diff changeset
4319 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4320 // Note: The new interval has no valid reg_num
a61af66fc99e Initial load
duke
parents:
diff changeset
4321 Interval* Interval::split(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4322 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4323
a61af66fc99e Initial load
duke
parents:
diff changeset
4324 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4325 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4326
a61af66fc99e Initial load
duke
parents:
diff changeset
4327 // split the ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4328 Range* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4329 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4330 while (cur != Range::end() && cur->to() <= split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4331 prev = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4332 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4333 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4334 assert(cur != Range::end(), "split interval after end of last range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4335
a61af66fc99e Initial load
duke
parents:
diff changeset
4336 if (cur->from() < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4337 result->_first = new Range(split_pos, cur->to(), cur->next());
a61af66fc99e Initial load
duke
parents:
diff changeset
4338 cur->set_to(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4339 cur->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4340
a61af66fc99e Initial load
duke
parents:
diff changeset
4341 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4342 assert(prev != NULL, "split before start of first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4343 result->_first = cur;
a61af66fc99e Initial load
duke
parents:
diff changeset
4344 prev->set_next(Range::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4346 result->_current = result->_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4347 _cached_to = -1; // clear cached value
a61af66fc99e Initial load
duke
parents:
diff changeset
4348
a61af66fc99e Initial load
duke
parents:
diff changeset
4349 // split list of use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4350 int total_len = _use_pos_and_kinds.length();
a61af66fc99e Initial load
duke
parents:
diff changeset
4351 int start_idx = total_len - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4352 while (start_idx >= 0 && _use_pos_and_kinds.at(start_idx) < split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4353 start_idx -= 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4354 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4355
a61af66fc99e Initial load
duke
parents:
diff changeset
4356 intStack new_use_pos_and_kinds(total_len - start_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
4357 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
4358 for (i = start_idx + 2; i < total_len; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4359 new_use_pos_and_kinds.append(_use_pos_and_kinds.at(i));
a61af66fc99e Initial load
duke
parents:
diff changeset
4360 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4361
a61af66fc99e Initial load
duke
parents:
diff changeset
4362 _use_pos_and_kinds.truncate(start_idx + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4363 result->_use_pos_and_kinds = _use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4364 _use_pos_and_kinds = new_use_pos_and_kinds;
a61af66fc99e Initial load
duke
parents:
diff changeset
4365
a61af66fc99e Initial load
duke
parents:
diff changeset
4366 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
4367 assert(_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4368 assert(result->_use_pos_and_kinds.length() % 2 == 0, "must have use kind for each use pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
4369 assert(_use_pos_and_kinds.length() + result->_use_pos_and_kinds.length() == total_len, "missed some entries");
a61af66fc99e Initial load
duke
parents:
diff changeset
4370
a61af66fc99e Initial load
duke
parents:
diff changeset
4371 for (i = 0; i < _use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4372 assert(_use_pos_and_kinds.at(i) < split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4373 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
4374 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4375 for (i = 0; i < result->_use_pos_and_kinds.length(); i += 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4376 assert(result->_use_pos_and_kinds.at(i) >= split_pos, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4377 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
4378 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4379 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4380
a61af66fc99e Initial load
duke
parents:
diff changeset
4381 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4382 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4383
a61af66fc99e Initial load
duke
parents:
diff changeset
4384 // split this interval at the specified position and return
a61af66fc99e Initial load
duke
parents:
diff changeset
4385 // the head as a new interval (the original interval is the tail)
a61af66fc99e Initial load
duke
parents:
diff changeset
4386 //
a61af66fc99e Initial load
duke
parents:
diff changeset
4387 // Currently, only the first range can be split, and the new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4388 // must not have split positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4389 Interval* Interval::split_from_start(int split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4390 assert(LinearScan::is_virtual_interval(this), "cannot split fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
4391 assert(split_pos > from() && split_pos < to(), "can only split inside interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4392 assert(split_pos > _first->from() && split_pos <= _first->to(), "can only split inside first range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4393 assert(first_usage(noUse) > split_pos, "can not split when use positions are present");
a61af66fc99e Initial load
duke
parents:
diff changeset
4394
a61af66fc99e Initial load
duke
parents:
diff changeset
4395 // allocate new interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4396 Interval* result = new_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
4397
a61af66fc99e Initial load
duke
parents:
diff changeset
4398 // the new created interval has only one range (checked by assertion above),
a61af66fc99e Initial load
duke
parents:
diff changeset
4399 // so the splitting of the ranges is very simple
a61af66fc99e Initial load
duke
parents:
diff changeset
4400 result->add_range(_first->from(), split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4401
a61af66fc99e Initial load
duke
parents:
diff changeset
4402 if (split_pos == _first->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4403 assert(_first->next() != Range::end(), "must not be at end");
a61af66fc99e Initial load
duke
parents:
diff changeset
4404 _first = _first->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4405 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4406 _first->set_from(split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4407 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4408
a61af66fc99e Initial load
duke
parents:
diff changeset
4409 return result;
a61af66fc99e Initial load
duke
parents:
diff changeset
4410 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4411
a61af66fc99e Initial load
duke
parents:
diff changeset
4412
a61af66fc99e Initial load
duke
parents:
diff changeset
4413 // returns true if the op_id is inside the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4414 bool Interval::covers(int op_id, LIR_OpVisitState::OprMode mode) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4415 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4416
a61af66fc99e Initial load
duke
parents:
diff changeset
4417 while (cur != Range::end() && cur->to() < op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4418 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4419 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4420 if (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4421 assert(cur->to() != cur->next()->from(), "ranges not separated");
a61af66fc99e Initial load
duke
parents:
diff changeset
4422
a61af66fc99e Initial load
duke
parents:
diff changeset
4423 if (mode == LIR_OpVisitState::outputMode) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4424 return cur->from() <= op_id && op_id < cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4425 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4426 return cur->from() <= op_id && op_id <= cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
4427 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4428 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4429 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4430 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4431
a61af66fc99e Initial load
duke
parents:
diff changeset
4432 // returns true if the interval has any hole between hole_from and hole_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4433 // (even if the hole has only the length 1)
a61af66fc99e Initial load
duke
parents:
diff changeset
4434 bool Interval::has_hole_between(int hole_from, int hole_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4435 assert(hole_from < hole_to, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4436 assert(from() <= hole_from && hole_to <= to(), "index out of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
4437
a61af66fc99e Initial load
duke
parents:
diff changeset
4438 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4439 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4440 assert(cur->to() < cur->next()->from(), "no space between ranges");
a61af66fc99e Initial load
duke
parents:
diff changeset
4441
a61af66fc99e Initial load
duke
parents:
diff changeset
4442 // hole-range starts before this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4443 if (hole_from < cur->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4444 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4445
a61af66fc99e Initial load
duke
parents:
diff changeset
4446 // hole-range completely inside this range -> no hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4447 } else if (hole_to <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4448 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4449
a61af66fc99e Initial load
duke
parents:
diff changeset
4450 // overlapping of hole-range with this range -> hole
a61af66fc99e Initial load
duke
parents:
diff changeset
4451 } else if (hole_from <= cur->to()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4452 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4453 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4454
a61af66fc99e Initial load
duke
parents:
diff changeset
4455 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4457
a61af66fc99e Initial load
duke
parents:
diff changeset
4458 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4459 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4460
a61af66fc99e Initial load
duke
parents:
diff changeset
4461
a61af66fc99e Initial load
duke
parents:
diff changeset
4462 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4463 void Interval::print(outputStream* out) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
4464 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
4465 const char* UseKind2Name[] = { "N", "L", "S", "M" };
a61af66fc99e Initial load
duke
parents:
diff changeset
4466
a61af66fc99e Initial load
duke
parents:
diff changeset
4467 const char* type_name;
a61af66fc99e Initial load
duke
parents:
diff changeset
4468 LIR_Opr opr = LIR_OprFact::illegal();
a61af66fc99e Initial load
duke
parents:
diff changeset
4469 if (reg_num() < LIR_OprDesc::vreg_base) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4470 type_name = "fixed";
a61af66fc99e Initial load
duke
parents:
diff changeset
4471 // need a temporary operand for fixed intervals because type() cannot be called
a61af66fc99e Initial load
duke
parents:
diff changeset
4472 if (assigned_reg() >= pd_first_cpu_reg && assigned_reg() <= pd_last_cpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4473 opr = LIR_OprFact::single_cpu(assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4474 } else if (assigned_reg() >= pd_first_fpu_reg && assigned_reg() <= pd_last_fpu_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4475 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
4476 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
4477 } else if (assigned_reg() >= pd_first_xmm_reg && assigned_reg() <= pd_last_xmm_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4478 opr = LIR_OprFact::single_xmm(assigned_reg() - pd_first_xmm_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
4479 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4480 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4481 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
4482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4483 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4484 type_name = type2name(type());
a61af66fc99e Initial load
duke
parents:
diff changeset
4485 if (assigned_reg() != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4486 opr = LinearScan::calc_operand_for_interval(this);
a61af66fc99e Initial load
duke
parents:
diff changeset
4487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4489
a61af66fc99e Initial load
duke
parents:
diff changeset
4490 out->print("%d %s ", reg_num(), type_name);
a61af66fc99e Initial load
duke
parents:
diff changeset
4491 if (opr->is_valid()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4492 out->print("\"");
a61af66fc99e Initial load
duke
parents:
diff changeset
4493 opr->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4494 out->print("\" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
4495 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4496 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
4497
a61af66fc99e Initial load
duke
parents:
diff changeset
4498 // print ranges
a61af66fc99e Initial load
duke
parents:
diff changeset
4499 Range* cur = _first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4500 while (cur != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4501 cur->print(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
4502 cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4503 assert(cur != NULL, "range list not closed with range sentinel");
a61af66fc99e Initial load
duke
parents:
diff changeset
4504 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4505
a61af66fc99e Initial load
duke
parents:
diff changeset
4506 // print use positions
a61af66fc99e Initial load
duke
parents:
diff changeset
4507 int prev = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4508 assert(_use_pos_and_kinds.length() % 2 == 0, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
4509 for (int i =_use_pos_and_kinds.length() - 2; i >= 0; i -= 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4510 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
4511 assert(prev < _use_pos_and_kinds.at(i), "use positions not sorted");
a61af66fc99e Initial load
duke
parents:
diff changeset
4512
a61af66fc99e Initial load
duke
parents:
diff changeset
4513 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
4514 prev = _use_pos_and_kinds.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4515 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4516
a61af66fc99e Initial load
duke
parents:
diff changeset
4517 out->print(" \"%s\"", SpillState2Name[spill_state()]);
a61af66fc99e Initial load
duke
parents:
diff changeset
4518 out->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4520 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4521
a61af66fc99e Initial load
duke
parents:
diff changeset
4522
a61af66fc99e Initial load
duke
parents:
diff changeset
4523
a61af66fc99e Initial load
duke
parents:
diff changeset
4524 // **** Implementation of IntervalWalker ****************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4525
a61af66fc99e Initial load
duke
parents:
diff changeset
4526 IntervalWalker::IntervalWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4527 : _compilation(allocator->compilation())
a61af66fc99e Initial load
duke
parents:
diff changeset
4528 , _allocator(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4529 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4530 _unhandled_first[fixedKind] = unhandled_fixed_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4531 _unhandled_first[anyKind] = unhandled_any_first;
a61af66fc99e Initial load
duke
parents:
diff changeset
4532 _active_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4533 _inactive_first[fixedKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4534 _active_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4535 _inactive_first[anyKind] = Interval::end();
a61af66fc99e Initial load
duke
parents:
diff changeset
4536 _current_position = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4537 _current = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4538 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4539 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4540
a61af66fc99e Initial load
duke
parents:
diff changeset
4541
a61af66fc99e Initial load
duke
parents:
diff changeset
4542 // append interval at top of list
a61af66fc99e Initial load
duke
parents:
diff changeset
4543 void IntervalWalker::append_unsorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4544 interval->set_next(*list); *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4546
a61af66fc99e Initial load
duke
parents:
diff changeset
4547
a61af66fc99e Initial load
duke
parents:
diff changeset
4548 // append interval in order of current range from()
a61af66fc99e Initial load
duke
parents:
diff changeset
4549 void IntervalWalker::append_sorted(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4550 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4551 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4552 while (cur->current_from() < interval->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4553 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4554 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4555 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4556 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4557 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4558 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4559 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4560 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4561 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4562
a61af66fc99e Initial load
duke
parents:
diff changeset
4563 void IntervalWalker::append_to_unhandled(Interval** list, Interval* interval) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4564 assert(interval->from() >= current()->current_from(), "cannot append new interval before current walk position");
a61af66fc99e Initial load
duke
parents:
diff changeset
4565
a61af66fc99e Initial load
duke
parents:
diff changeset
4566 Interval* prev = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
4567 Interval* cur = *list;
a61af66fc99e Initial load
duke
parents:
diff changeset
4568 while (cur->from() < interval->from() || (cur->from() == interval->from() && cur->first_usage(noUse) < interval->first_usage(noUse))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4569 prev = cur; cur = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4571 if (prev == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4572 *list = interval;
a61af66fc99e Initial load
duke
parents:
diff changeset
4573 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4574 prev->set_next(interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
4575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4576 interval->set_next(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4577 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4578
a61af66fc99e Initial load
duke
parents:
diff changeset
4579
a61af66fc99e Initial load
duke
parents:
diff changeset
4580 inline bool IntervalWalker::remove_from_list(Interval** list, Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4581 while (*list != Interval::end() && *list != i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4582 list = (*list)->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4583 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4584 if (*list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4585 assert(*list == i, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4586 *list = (*list)->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4587 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4588 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4589 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4590 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4592
a61af66fc99e Initial load
duke
parents:
diff changeset
4593 void IntervalWalker::remove_from_list(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4594 bool deleted;
a61af66fc99e Initial load
duke
parents:
diff changeset
4595
a61af66fc99e Initial load
duke
parents:
diff changeset
4596 if (i->state() == activeState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4597 deleted = remove_from_list(active_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4598 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4599 assert(i->state() == inactiveState, "invalid state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4600 deleted = remove_from_list(inactive_first_addr(anyKind), i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4601 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4602
a61af66fc99e Initial load
duke
parents:
diff changeset
4603 assert(deleted, "interval has not been found in list");
a61af66fc99e Initial load
duke
parents:
diff changeset
4604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4605
a61af66fc99e Initial load
duke
parents:
diff changeset
4606
a61af66fc99e Initial load
duke
parents:
diff changeset
4607 void IntervalWalker::walk_to(IntervalState state, int from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4608 assert (state == activeState || state == inactiveState, "wrong state");
a61af66fc99e Initial load
duke
parents:
diff changeset
4609 for_each_interval_kind(kind) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4610 Interval** prev = state == activeState ? active_first_addr(kind) : inactive_first_addr(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4611 Interval* next = *prev;
a61af66fc99e Initial load
duke
parents:
diff changeset
4612 while (next->current_from() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4613 Interval* cur = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4614 next = cur->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4615
a61af66fc99e Initial load
duke
parents:
diff changeset
4616 bool range_has_changed = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
4617 while (cur->current_to() <= from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4618 cur->next_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4619 range_has_changed = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
4620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4621
a61af66fc99e Initial load
duke
parents:
diff changeset
4622 // also handle move from inactive list to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4623 range_has_changed = range_has_changed || (state == inactiveState && cur->current_from() <= from);
a61af66fc99e Initial load
duke
parents:
diff changeset
4624
a61af66fc99e Initial load
duke
parents:
diff changeset
4625 if (range_has_changed) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4626 // remove cur from list
a61af66fc99e Initial load
duke
parents:
diff changeset
4627 *prev = next;
a61af66fc99e Initial load
duke
parents:
diff changeset
4628 if (cur->current_at_end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4629 // move to handled state (not maintained as a list)
a61af66fc99e Initial load
duke
parents:
diff changeset
4630 cur->set_state(handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4631 interval_moved(cur, kind, state, handledState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4632 } else if (cur->current_from() <= from){
a61af66fc99e Initial load
duke
parents:
diff changeset
4633 // sort into active list
a61af66fc99e Initial load
duke
parents:
diff changeset
4634 append_sorted(active_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4635 cur->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4636 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4637 assert(state == activeState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4638 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4640 interval_moved(cur, kind, state, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4641 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4642 // sort into inactive list
a61af66fc99e Initial load
duke
parents:
diff changeset
4643 append_sorted(inactive_first_addr(kind), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
4644 cur->set_state(inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4645 if (*prev == cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4646 assert(state == inactiveState, "check");
a61af66fc99e Initial load
duke
parents:
diff changeset
4647 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4648 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4649 interval_moved(cur, kind, state, inactiveState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4650 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4651 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4652 prev = cur->next_addr();
a61af66fc99e Initial load
duke
parents:
diff changeset
4653 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
4654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4655 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4656 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4657 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4658
a61af66fc99e Initial load
duke
parents:
diff changeset
4659
a61af66fc99e Initial load
duke
parents:
diff changeset
4660 void IntervalWalker::next_interval() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4661 IntervalKind kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4662 Interval* any = _unhandled_first[anyKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4663 Interval* fixed = _unhandled_first[fixedKind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4664
a61af66fc99e Initial load
duke
parents:
diff changeset
4665 if (any != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4666 // intervals may start at same position -> prefer fixed interval
a61af66fc99e Initial load
duke
parents:
diff changeset
4667 kind = fixed != Interval::end() && fixed->from() <= any->from() ? fixedKind : anyKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4668
a61af66fc99e Initial load
duke
parents:
diff changeset
4669 assert (kind == fixedKind && fixed->from() <= any->from() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
4670 kind == anyKind && any->from() <= fixed->from(), "wrong interval!!!");
a61af66fc99e Initial load
duke
parents:
diff changeset
4671 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
4672
a61af66fc99e Initial load
duke
parents:
diff changeset
4673 } else if (fixed != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4674 kind = fixedKind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4675 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4676 _current = NULL; return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4677 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4678 _current_kind = kind;
a61af66fc99e Initial load
duke
parents:
diff changeset
4679 _current = _unhandled_first[kind];
a61af66fc99e Initial load
duke
parents:
diff changeset
4680 _unhandled_first[kind] = _current->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4681 _current->set_next(Interval::end());
a61af66fc99e Initial load
duke
parents:
diff changeset
4682 _current->rewind_range();
a61af66fc99e Initial load
duke
parents:
diff changeset
4683 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4684
a61af66fc99e Initial load
duke
parents:
diff changeset
4685
a61af66fc99e Initial load
duke
parents:
diff changeset
4686 void IntervalWalker::walk_to(int lir_op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4687 assert(_current_position <= lir_op_id, "can not walk backwards");
a61af66fc99e Initial load
duke
parents:
diff changeset
4688 while (current() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4689 bool is_active = current()->from() <= lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4690 int id = is_active ? current()->from() : lir_op_id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4691
a61af66fc99e Initial load
duke
parents:
diff changeset
4692 TRACE_LINEAR_SCAN(2, if (_current_position < id) { tty->cr(); tty->print_cr("walk_to(%d) **************************************************************", id); })
a61af66fc99e Initial load
duke
parents:
diff changeset
4693
a61af66fc99e Initial load
duke
parents:
diff changeset
4694 // set _current_position prior to call of walk_to
a61af66fc99e Initial load
duke
parents:
diff changeset
4695 _current_position = id;
a61af66fc99e Initial load
duke
parents:
diff changeset
4696
a61af66fc99e Initial load
duke
parents:
diff changeset
4697 // call walk_to even if _current_position == id
a61af66fc99e Initial load
duke
parents:
diff changeset
4698 walk_to(activeState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4699 walk_to(inactiveState, id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4700
a61af66fc99e Initial load
duke
parents:
diff changeset
4701 if (is_active) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4702 current()->set_state(activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4703 if (activate_current()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4704 append_sorted(active_first_addr(current_kind()), current());
a61af66fc99e Initial load
duke
parents:
diff changeset
4705 interval_moved(current(), current_kind(), unhandledState, activeState);
a61af66fc99e Initial load
duke
parents:
diff changeset
4706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4707
a61af66fc99e Initial load
duke
parents:
diff changeset
4708 next_interval();
a61af66fc99e Initial load
duke
parents:
diff changeset
4709 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4710 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
4711 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4712 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4713 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4714
a61af66fc99e Initial load
duke
parents:
diff changeset
4715 void IntervalWalker::interval_moved(Interval* interval, IntervalKind kind, IntervalState from, IntervalState to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4716 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
4717 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4718 #define print_state(state) \
a61af66fc99e Initial load
duke
parents:
diff changeset
4719 switch(state) {\
a61af66fc99e Initial load
duke
parents:
diff changeset
4720 case unhandledState: tty->print("unhandled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4721 case activeState: tty->print("active"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4722 case inactiveState: tty->print("inactive"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4723 case handledState: tty->print("handled"); break;\
a61af66fc99e Initial load
duke
parents:
diff changeset
4724 default: ShouldNotReachHere(); \
a61af66fc99e Initial load
duke
parents:
diff changeset
4725 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4726
a61af66fc99e Initial load
duke
parents:
diff changeset
4727 print_state(from); tty->print(" to "); print_state(to);
a61af66fc99e Initial load
duke
parents:
diff changeset
4728 tty->fill_to(23);
a61af66fc99e Initial load
duke
parents:
diff changeset
4729 interval->print();
a61af66fc99e Initial load
duke
parents:
diff changeset
4730
a61af66fc99e Initial load
duke
parents:
diff changeset
4731 #undef print_state
a61af66fc99e Initial load
duke
parents:
diff changeset
4732 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4733 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
4734 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4735
a61af66fc99e Initial load
duke
parents:
diff changeset
4736
a61af66fc99e Initial load
duke
parents:
diff changeset
4737
a61af66fc99e Initial load
duke
parents:
diff changeset
4738 // **** Implementation of LinearScanWalker **************************
a61af66fc99e Initial load
duke
parents:
diff changeset
4739
a61af66fc99e Initial load
duke
parents:
diff changeset
4740 LinearScanWalker::LinearScanWalker(LinearScan* allocator, Interval* unhandled_fixed_first, Interval* unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4741 : IntervalWalker(allocator, unhandled_fixed_first, unhandled_any_first)
a61af66fc99e Initial load
duke
parents:
diff changeset
4742 , _move_resolver(allocator)
a61af66fc99e Initial load
duke
parents:
diff changeset
4743 {
a61af66fc99e Initial load
duke
parents:
diff changeset
4744 for (int i = 0; i < LinearScan::nof_regs; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4745 _spill_intervals[i] = new IntervalList(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
4746 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4747 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4748
a61af66fc99e Initial load
duke
parents:
diff changeset
4749
a61af66fc99e Initial load
duke
parents:
diff changeset
4750 inline void LinearScanWalker::init_use_lists(bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4751 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4752 _use_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4753
a61af66fc99e Initial load
duke
parents:
diff changeset
4754 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4755 _block_pos[i] = max_jint;
a61af66fc99e Initial load
duke
parents:
diff changeset
4756 _spill_intervals[i]->clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
4757 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4758 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4759 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4760
a61af66fc99e Initial load
duke
parents:
diff changeset
4761 inline void LinearScanWalker::exclude_from_use(int reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4762 assert(reg < LinearScan::nof_regs, "interval must have a register assigned (stack slots not allowed)");
a61af66fc99e Initial load
duke
parents:
diff changeset
4763 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4764 _use_pos[reg] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
4765 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4766 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4767 inline void LinearScanWalker::exclude_from_use(Interval* i) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4768 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4769
a61af66fc99e Initial load
duke
parents:
diff changeset
4770 exclude_from_use(i->assigned_reg());
a61af66fc99e Initial load
duke
parents:
diff changeset
4771 exclude_from_use(i->assigned_regHi());
a61af66fc99e Initial load
duke
parents:
diff changeset
4772 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4773
a61af66fc99e Initial load
duke
parents:
diff changeset
4774 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
4775 assert(use_pos != 0, "must use exclude_from_use to set use_pos to 0");
a61af66fc99e Initial load
duke
parents:
diff changeset
4776
a61af66fc99e Initial load
duke
parents:
diff changeset
4777 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4778 if (_use_pos[reg] > use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4779 _use_pos[reg] = use_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4780 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4781 if (!only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4782 _spill_intervals[reg]->append(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4783 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4784 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4785 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4786 inline void LinearScanWalker::set_use_pos(Interval* i, int use_pos, bool only_process_use_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4787 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4788 if (use_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4789 set_use_pos(i->assigned_reg(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4790 set_use_pos(i->assigned_regHi(), i, use_pos, only_process_use_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4791 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4792 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4793
a61af66fc99e Initial load
duke
parents:
diff changeset
4794 inline void LinearScanWalker::set_block_pos(int reg, Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4795 if (reg >= _first_reg && reg <= _last_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4796 if (_block_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4797 _block_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4798 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4799 if (_use_pos[reg] > block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4800 _use_pos[reg] = block_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4801 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4802 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4803 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4804 inline void LinearScanWalker::set_block_pos(Interval* i, int block_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4805 assert(i->assigned_reg() != any_reg, "interval has no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4806 if (block_pos != -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4807 set_block_pos(i->assigned_reg(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4808 set_block_pos(i->assigned_regHi(), i, block_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
4809 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4810 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4811
a61af66fc99e Initial load
duke
parents:
diff changeset
4812
a61af66fc99e Initial load
duke
parents:
diff changeset
4813 void LinearScanWalker::free_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4814 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4815 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4816 assert(list->assigned_reg() < LinearScan::nof_regs, "active interval must have a register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
4817 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4818 list = list->next();
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 void LinearScanWalker::free_exclude_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4823 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4824 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4825 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4826 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4827 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4828 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4829
a61af66fc99e Initial load
duke
parents:
diff changeset
4830 void LinearScanWalker::free_collect_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4831 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4832 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4833 if (cur->to() <= list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4834 assert(list->current_intersects_at(cur) == -1, "must not intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4835 set_use_pos(list, list->current_from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4836 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4837 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4838 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4839 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4840 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4841 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4842
a61af66fc99e Initial load
duke
parents:
diff changeset
4843 void LinearScanWalker::free_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4844 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4845 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4846 set_use_pos(list, list->current_intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4847 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4848 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4849 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4850
a61af66fc99e Initial load
duke
parents:
diff changeset
4851 void LinearScanWalker::free_collect_unhandled(IntervalKind kind, Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4852 Interval* list = unhandled_first(kind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4853 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4854 set_use_pos(list, list->intersects_at(cur), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4855 if (kind == fixedKind && cur->to() <= list->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4856 set_use_pos(list, list->from(), true);
a61af66fc99e Initial load
duke
parents:
diff changeset
4857 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4858 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4860 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4861
a61af66fc99e Initial load
duke
parents:
diff changeset
4862 void LinearScanWalker::spill_exclude_active_fixed() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4863 Interval* list = active_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4864 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4865 exclude_from_use(list);
a61af66fc99e Initial load
duke
parents:
diff changeset
4866 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4867 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4868 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4869
a61af66fc99e Initial load
duke
parents:
diff changeset
4870 void LinearScanWalker::spill_block_unhandled_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4871 Interval* list = unhandled_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4872 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4873 set_block_pos(list, list->intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4874 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4876 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4877
a61af66fc99e Initial load
duke
parents:
diff changeset
4878 void LinearScanWalker::spill_block_inactive_fixed(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4879 Interval* list = inactive_first(fixedKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4880 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4881 if (cur->to() > list->current_from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4882 set_block_pos(list, list->current_intersects_at(cur));
a61af66fc99e Initial load
duke
parents:
diff changeset
4883 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4884 assert(list->current_intersects_at(cur) == -1, "invalid optimization: intervals intersect");
a61af66fc99e Initial load
duke
parents:
diff changeset
4885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4886
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::spill_collect_active_any() {
a61af66fc99e Initial load
duke
parents:
diff changeset
4892 Interval* list = active_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4893 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4894 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4895 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4896 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4897 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4898
a61af66fc99e Initial load
duke
parents:
diff changeset
4899 void LinearScanWalker::spill_collect_inactive_any(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4900 Interval* list = inactive_first(anyKind);
a61af66fc99e Initial load
duke
parents:
diff changeset
4901 while (list != Interval::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4902 if (list->current_intersects(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4903 set_use_pos(list, MIN2(list->next_usage(loopEndMarker, _current_position), list->to()), false);
a61af66fc99e Initial load
duke
parents:
diff changeset
4904 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4905 list = list->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
4906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4907 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4908
a61af66fc99e Initial load
duke
parents:
diff changeset
4909
a61af66fc99e Initial load
duke
parents:
diff changeset
4910 void LinearScanWalker::insert_move(int op_id, Interval* src_it, Interval* dst_it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4911 // output all moves here. When source and target are equal, the move is
a61af66fc99e Initial load
duke
parents:
diff changeset
4912 // optimized away later in assign_reg_nums
a61af66fc99e Initial load
duke
parents:
diff changeset
4913
a61af66fc99e Initial load
duke
parents:
diff changeset
4914 op_id = (op_id + 1) & ~1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4915 BlockBegin* op_block = allocator()->block_of_op_with_id(op_id);
a61af66fc99e Initial load
duke
parents:
diff changeset
4916 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
4917
a61af66fc99e Initial load
duke
parents:
diff changeset
4918 // calculate index of instruction inside instruction list of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
4919 // the minimal index (for a block with no spill moves) can be calculated because the
a61af66fc99e Initial load
duke
parents:
diff changeset
4920 // numbering of instructions is known.
a61af66fc99e Initial load
duke
parents:
diff changeset
4921 // When the block already contains spill moves, the index must be increased until the
a61af66fc99e Initial load
duke
parents:
diff changeset
4922 // correct index is reached.
a61af66fc99e Initial load
duke
parents:
diff changeset
4923 LIR_OpList* list = op_block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
4924 int index = (op_id - list->at(0)->id()) / 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4925 assert(list->at(index)->id() <= op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4926
a61af66fc99e Initial load
duke
parents:
diff changeset
4927 while (list->at(index)->id() != op_id) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4928 index++;
a61af66fc99e Initial load
duke
parents:
diff changeset
4929 assert(0 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
4930 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4931 assert(1 <= index && index < list->length(), "index out of bounds");
a61af66fc99e Initial load
duke
parents:
diff changeset
4932 assert(list->at(index)->id() == op_id, "error in calculation");
a61af66fc99e Initial load
duke
parents:
diff changeset
4933
a61af66fc99e Initial load
duke
parents:
diff changeset
4934 // insert new instruction before instruction at position index
a61af66fc99e Initial load
duke
parents:
diff changeset
4935 _move_resolver.move_insert_position(op_block->lir(), index - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4936 _move_resolver.add_mapping(src_it, dst_it);
a61af66fc99e Initial load
duke
parents:
diff changeset
4937 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4938
a61af66fc99e Initial load
duke
parents:
diff changeset
4939
a61af66fc99e Initial load
duke
parents:
diff changeset
4940 int LinearScanWalker::find_optimal_split_pos(BlockBegin* min_block, BlockBegin* max_block, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4941 int from_block_nr = min_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
4942 int to_block_nr = max_block->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
4943
a61af66fc99e Initial load
duke
parents:
diff changeset
4944 assert(0 <= from_block_nr && from_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4945 assert(0 <= to_block_nr && to_block_nr < block_count(), "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
4946 assert(from_block_nr < to_block_nr, "must cross block boundary");
a61af66fc99e Initial load
duke
parents:
diff changeset
4947
a61af66fc99e Initial load
duke
parents:
diff changeset
4948 // Try to split at end of max_block. If this would be after
a61af66fc99e Initial load
duke
parents:
diff changeset
4949 // max_split_pos, then use the begin of max_block
a61af66fc99e Initial load
duke
parents:
diff changeset
4950 int optimal_split_pos = max_block->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4951 if (optimal_split_pos > max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4952 optimal_split_pos = max_block->first_lir_instruction_id();
a61af66fc99e Initial load
duke
parents:
diff changeset
4953 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4954
a61af66fc99e Initial load
duke
parents:
diff changeset
4955 int min_loop_depth = max_block->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
4956 for (int i = to_block_nr - 1; i >= from_block_nr; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4957 BlockBegin* cur = block_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
4958
a61af66fc99e Initial load
duke
parents:
diff changeset
4959 if (cur->loop_depth() < min_loop_depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4960 // block with lower loop-depth found -> split at the end of this block
a61af66fc99e Initial load
duke
parents:
diff changeset
4961 min_loop_depth = cur->loop_depth();
a61af66fc99e Initial load
duke
parents:
diff changeset
4962 optimal_split_pos = cur->last_lir_instruction_id() + 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
4963 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4964 }
a61af66fc99e Initial load
duke
parents:
diff changeset
4965 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
4966
a61af66fc99e Initial load
duke
parents:
diff changeset
4967 return optimal_split_pos;
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 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
4972 int optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
4973 if (min_split_pos == max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4974 // trivial case, no optimization of split position possible
a61af66fc99e Initial load
duke
parents:
diff changeset
4975 TRACE_LINEAR_SCAN(4, tty->print_cr(" min-pos and max-pos are equal, no optimization possible"));
a61af66fc99e Initial load
duke
parents:
diff changeset
4976 optimal_split_pos = min_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4977
a61af66fc99e Initial load
duke
parents:
diff changeset
4978 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
4979 assert(min_split_pos < max_split_pos, "must be true then");
a61af66fc99e Initial load
duke
parents:
diff changeset
4980 assert(min_split_pos > 0, "cannot access min_split_pos - 1 otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
4981
a61af66fc99e Initial load
duke
parents:
diff changeset
4982 // reason for using min_split_pos - 1: when the minimal split pos is exactly at the
a61af66fc99e Initial load
duke
parents:
diff changeset
4983 // beginning of a block, then min_split_pos is also a possible split position.
a61af66fc99e Initial load
duke
parents:
diff changeset
4984 // 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
4985 BlockBegin* min_block = allocator()->block_of_op_with_id(min_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4986
a61af66fc99e Initial load
duke
parents:
diff changeset
4987 // reason for using max_split_pos - 1: otherwise there would be an assertion failure
a61af66fc99e Initial load
duke
parents:
diff changeset
4988 // when an interval ends at the end of the last block of the method
a61af66fc99e Initial load
duke
parents:
diff changeset
4989 // (in this case, max_split_pos == allocator()->max_lir_op_id() + 2, and there is no
a61af66fc99e Initial load
duke
parents:
diff changeset
4990 // block at this op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
4991 BlockBegin* max_block = allocator()->block_of_op_with_id(max_split_pos - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
4992
a61af66fc99e Initial load
duke
parents:
diff changeset
4993 assert(min_block->linear_scan_number() <= max_block->linear_scan_number(), "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
4994 if (min_block == max_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
4995 // split position cannot be moved to block boundary, so split as late as possible
a61af66fc99e Initial load
duke
parents:
diff changeset
4996 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
4997 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
4998
a61af66fc99e Initial load
duke
parents:
diff changeset
4999 } 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
5000 // Do not move split position if the interval has a hole before max_split_pos.
a61af66fc99e Initial load
duke
parents:
diff changeset
5001 // Intervals resulting from Phi-Functions have more than one definition (marked
a61af66fc99e Initial load
duke
parents:
diff changeset
5002 // as mustHaveRegister) with a hole before each definition. When the register is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5003 // for the second definition, an earlier reloading is unnecessary.
a61af66fc99e Initial load
duke
parents:
diff changeset
5004 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
5005 optimal_split_pos = max_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5006
a61af66fc99e Initial load
duke
parents:
diff changeset
5007 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5008 // seach optimal block boundary between min_split_pos and max_split_pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5009 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
5010
a61af66fc99e Initial load
duke
parents:
diff changeset
5011 if (do_loop_optimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5012 // Loop optimization: if a loop-end marker is found between min- and max-position,
a61af66fc99e Initial load
duke
parents:
diff changeset
5013 // then split before this loop
a61af66fc99e Initial load
duke
parents:
diff changeset
5014 int loop_end_pos = it->next_usage_exact(loopEndMarker, min_block->last_lir_instruction_id() + 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5015 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
5016
a61af66fc99e Initial load
duke
parents:
diff changeset
5017 assert(loop_end_pos > min_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5018 if (loop_end_pos < max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5019 // loop-end marker found between min- and max-position
a61af66fc99e Initial load
duke
parents:
diff changeset
5020 // if it is not the end marker for the same loop as the min-position, then move
a61af66fc99e Initial load
duke
parents:
diff changeset
5021 // the max-position to this loop block.
a61af66fc99e Initial load
duke
parents:
diff changeset
5022 // Desired result: uses tagged as shouldHaveRegister inside a loop cause a reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5023 // of the interval (normally, only mustHaveRegister causes a reloading)
a61af66fc99e Initial load
duke
parents:
diff changeset
5024 BlockBegin* loop_block = allocator()->block_of_op_with_id(loop_end_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5025
a61af66fc99e Initial load
duke
parents:
diff changeset
5026 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
5027 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
5028
a61af66fc99e Initial load
duke
parents:
diff changeset
5029 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
5030 if (optimal_split_pos == loop_block->last_lir_instruction_id() + 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5031 optimal_split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5032 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization not necessary"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5033 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5034 TRACE_LINEAR_SCAN(4, tty->print_cr(" loop optimization successful"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5035 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5036 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5038
a61af66fc99e Initial load
duke
parents:
diff changeset
5039 if (optimal_split_pos == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5040 // not calculated by loop optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5041 optimal_split_pos = find_optimal_split_pos(min_block, max_block, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5042 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5043 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5044 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5045 TRACE_LINEAR_SCAN(4, tty->print_cr(" optimal split position: %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5046
a61af66fc99e Initial load
duke
parents:
diff changeset
5047 return optimal_split_pos;
a61af66fc99e Initial load
duke
parents:
diff changeset
5048 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5049
a61af66fc99e Initial load
duke
parents:
diff changeset
5050
a61af66fc99e Initial load
duke
parents:
diff changeset
5051 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5052 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5053 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5054 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5055 2) the right part is sorted into to the unhandled-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5056 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5057 void LinearScanWalker::split_before_usage(Interval* it, int min_split_pos, int max_split_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5058 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5059 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5060
a61af66fc99e Initial load
duke
parents:
diff changeset
5061 assert(it->from() < min_split_pos, "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5062 assert(current_position() < min_split_pos, "cannot split before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5063 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5064 assert(max_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5065
a61af66fc99e Initial load
duke
parents:
diff changeset
5066 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5067
a61af66fc99e Initial load
duke
parents:
diff changeset
5068 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5069 assert(optimal_split_pos <= it->to(), "cannot split after end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5070 assert(optimal_split_pos > it->from(), "cannot split at start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5071
a61af66fc99e Initial load
duke
parents:
diff changeset
5072 if (optimal_split_pos == it->to() && it->next_usage(mustHaveRegister, min_split_pos) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5073 // the split position would be just before the end of the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5074 // -> no split at all necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5075 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
5076 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5077 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5078
a61af66fc99e Initial load
duke
parents:
diff changeset
5079 // 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
5080 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
5081
a61af66fc99e Initial load
duke
parents:
diff changeset
5082 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5083 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5084 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5085 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5086
a61af66fc99e Initial load
duke
parents:
diff changeset
5087 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5088 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
5089 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
5090
a61af66fc99e Initial load
duke
parents:
diff changeset
5091 Interval* split_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5092
a61af66fc99e Initial load
duke
parents:
diff changeset
5093 allocator()->append_interval(split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5094 allocator()->copy_register_flags(it, split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5095 split_part->set_insert_move_when_activated(move_necessary);
a61af66fc99e Initial load
duke
parents:
diff changeset
5096 append_to_unhandled(unhandled_first_addr(anyKind), split_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5097
a61af66fc99e Initial load
duke
parents:
diff changeset
5098 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
5099 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5100 TRACE_LINEAR_SCAN(2, tty->print (" "); split_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5102
a61af66fc99e Initial load
duke
parents:
diff changeset
5103 /*
a61af66fc99e Initial load
duke
parents:
diff changeset
5104 split an interval at the optimal position between min_split_pos and
a61af66fc99e Initial load
duke
parents:
diff changeset
5105 max_split_pos in two parts:
a61af66fc99e Initial load
duke
parents:
diff changeset
5106 1) the left part has already a location assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5107 2) the right part is always on the stack and therefore ignored in further processing
a61af66fc99e Initial load
duke
parents:
diff changeset
5108 */
a61af66fc99e Initial load
duke
parents:
diff changeset
5109 void LinearScanWalker::split_for_spilling(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5110 // calculate allowed range of splitting position
a61af66fc99e Initial load
duke
parents:
diff changeset
5111 int max_split_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5112 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, max_split_pos) + 1, it->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5113
a61af66fc99e Initial load
duke
parents:
diff changeset
5114 TRACE_LINEAR_SCAN(2, tty->print ("----- splitting and spilling interval: "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5115 TRACE_LINEAR_SCAN(2, tty->print_cr(" between %d and %d", min_split_pos, max_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5116
a61af66fc99e Initial load
duke
parents:
diff changeset
5117 assert(it->state() == activeState, "why spill interval that is not active?");
a61af66fc99e Initial load
duke
parents:
diff changeset
5118 assert(it->from() <= min_split_pos, "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5119 assert(min_split_pos <= max_split_pos, "invalid order");
a61af66fc99e Initial load
duke
parents:
diff changeset
5120 assert(max_split_pos < it->to(), "cannot split at end end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5121 assert(current_position() < it->to(), "interval must not end before current position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5122
a61af66fc99e Initial load
duke
parents:
diff changeset
5123 if (min_split_pos == it->from()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5124 // the whole interval is never used, so spill it entirely to memory
a61af66fc99e Initial load
duke
parents:
diff changeset
5125 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
5126 assert(it->first_usage(shouldHaveRegister) > current_position(), "interval must not have use position before current_position");
a61af66fc99e Initial load
duke
parents:
diff changeset
5127
a61af66fc99e Initial load
duke
parents:
diff changeset
5128 allocator()->assign_spill_slot(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5129 allocator()->change_spill_state(it, min_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5130
a61af66fc99e Initial load
duke
parents:
diff changeset
5131 // Also kick parent intervals out of register to memory when they have no use
a61af66fc99e Initial load
duke
parents:
diff changeset
5132 // position. This avoids short interval in register surrounded by intervals in
a61af66fc99e Initial load
duke
parents:
diff changeset
5133 // memory -> avoid useless moves from memory to register and back
a61af66fc99e Initial load
duke
parents:
diff changeset
5134 Interval* parent = it;
a61af66fc99e Initial load
duke
parents:
diff changeset
5135 while (parent != NULL && parent->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5136 parent = parent->split_child_before_op_id(parent->from());
a61af66fc99e Initial load
duke
parents:
diff changeset
5137
a61af66fc99e Initial load
duke
parents:
diff changeset
5138 if (parent->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5139 if (parent->first_usage(shouldHaveRegister) == max_jint) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5140 // parent is never used, so kick it out of its assigned register
a61af66fc99e Initial load
duke
parents:
diff changeset
5141 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
5142 allocator()->assign_spill_slot(parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
5143 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5144 // do not go further back because the register is actually used by the interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5145 parent = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5147 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5149
a61af66fc99e Initial load
duke
parents:
diff changeset
5150 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5151 // search optimal split pos, split interval and spill only the right hand part
a61af66fc99e Initial load
duke
parents:
diff changeset
5152 int optimal_split_pos = find_optimal_split_pos(it, min_split_pos, max_split_pos, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5153
a61af66fc99e Initial load
duke
parents:
diff changeset
5154 assert(min_split_pos <= optimal_split_pos && optimal_split_pos <= max_split_pos, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5155 assert(optimal_split_pos < it->to(), "cannot split at end of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5156 assert(optimal_split_pos >= it->from(), "cannot split before start of interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5157
a61af66fc99e Initial load
duke
parents:
diff changeset
5158 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5159 // move position before actual instruction (odd op_id)
a61af66fc99e Initial load
duke
parents:
diff changeset
5160 optimal_split_pos = (optimal_split_pos - 1) | 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5162
a61af66fc99e Initial load
duke
parents:
diff changeset
5163 TRACE_LINEAR_SCAN(4, tty->print_cr(" splitting at position %d", optimal_split_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
5164 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
5165 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
5166
a61af66fc99e Initial load
duke
parents:
diff changeset
5167 Interval* spilled_part = it->split(optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5168 allocator()->append_interval(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5169 allocator()->assign_spill_slot(spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5170 allocator()->change_spill_state(spilled_part, optimal_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5171
a61af66fc99e Initial load
duke
parents:
diff changeset
5172 if (!allocator()->is_block_begin(optimal_split_pos)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5173 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
5174 insert_move(optimal_split_pos, it, spilled_part);
a61af66fc99e Initial load
duke
parents:
diff changeset
5175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5176
a61af66fc99e Initial load
duke
parents:
diff changeset
5177 // the current_split_child is needed later when moves are inserted for reloading
a61af66fc99e Initial load
duke
parents:
diff changeset
5178 assert(spilled_part->current_split_child() == it, "overwriting wrong current_split_child");
a61af66fc99e Initial load
duke
parents:
diff changeset
5179 spilled_part->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5180
a61af66fc99e Initial load
duke
parents:
diff changeset
5181 TRACE_LINEAR_SCAN(2, tty->print_cr(" split interval in two parts"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5182 TRACE_LINEAR_SCAN(2, tty->print (" "); it->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5183 TRACE_LINEAR_SCAN(2, tty->print (" "); spilled_part->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5184 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5186
a61af66fc99e Initial load
duke
parents:
diff changeset
5187
a61af66fc99e Initial load
duke
parents:
diff changeset
5188 void LinearScanWalker::split_stack_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5189 int min_split_pos = current_position() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5190 int max_split_pos = MIN2(it->first_usage(shouldHaveRegister), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5191
a61af66fc99e Initial load
duke
parents:
diff changeset
5192 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5194
a61af66fc99e Initial load
duke
parents:
diff changeset
5195 void LinearScanWalker::split_when_partial_register_available(Interval* it, int register_available_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5196 int min_split_pos = MAX2(it->previous_usage(shouldHaveRegister, register_available_until), it->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5197 int max_split_pos = register_available_until;
a61af66fc99e Initial load
duke
parents:
diff changeset
5198
a61af66fc99e Initial load
duke
parents:
diff changeset
5199 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5201
a61af66fc99e Initial load
duke
parents:
diff changeset
5202 void LinearScanWalker::split_and_spill_interval(Interval* it) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5203 assert(it->state() == activeState || it->state() == inactiveState, "other states not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5204
a61af66fc99e Initial load
duke
parents:
diff changeset
5205 int current_pos = current_position();
a61af66fc99e Initial load
duke
parents:
diff changeset
5206 if (it->state() == inactiveState) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5207 // the interval is currently inactive, so no spill slot is needed for now.
a61af66fc99e Initial load
duke
parents:
diff changeset
5208 // when the split part is activated, the interval has a new chance to get a register,
a61af66fc99e Initial load
duke
parents:
diff changeset
5209 // so in the best case no stack slot is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
5210 assert(it->has_hole_between(current_pos - 1, current_pos + 1), "interval can not be inactive otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5211 split_before_usage(it, current_pos + 1, current_pos + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5212
a61af66fc99e Initial load
duke
parents:
diff changeset
5213 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5214 // search the position where the interval must have a register and split
a61af66fc99e Initial load
duke
parents:
diff changeset
5215 // at the optimal position before.
a61af66fc99e Initial load
duke
parents:
diff changeset
5216 // The new created part is added to the unhandled list and will get a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5217 // when it is activated
a61af66fc99e Initial load
duke
parents:
diff changeset
5218 int min_split_pos = current_pos + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5219 int max_split_pos = MIN2(it->next_usage(mustHaveRegister, min_split_pos), it->to());
a61af66fc99e Initial load
duke
parents:
diff changeset
5220
a61af66fc99e Initial load
duke
parents:
diff changeset
5221 split_before_usage(it, min_split_pos, max_split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5222
a61af66fc99e Initial load
duke
parents:
diff changeset
5223 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
5224 split_for_spilling(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5226 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5227
a61af66fc99e Initial load
duke
parents:
diff changeset
5228
a61af66fc99e Initial load
duke
parents:
diff changeset
5229 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
5230 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5231 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5232
a61af66fc99e Initial load
duke
parents:
diff changeset
5233 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5234 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5235 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5236
a61af66fc99e Initial load
duke
parents:
diff changeset
5237 } else if (_use_pos[i] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5238 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5239 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
5240 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5242 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5243 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5244 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
5245 max_partial_reg = i;
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
a61af66fc99e Initial load
duke
parents:
diff changeset
5250 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5251 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5252 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5253 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5254 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5255 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5256 return any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5257 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5258 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5259
a61af66fc99e Initial load
duke
parents:
diff changeset
5260 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
5261 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5262
a61af66fc99e Initial load
duke
parents:
diff changeset
5263 int min_full_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5264 int max_partial_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5265
a61af66fc99e Initial load
duke
parents:
diff changeset
5266 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5267 if (_use_pos[i] >= interval_to && _use_pos[i + 1] >= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5268 // this register is free for the full interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5269 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
5270 min_full_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5272 } else if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5273 // this register is at least free until reg_needed_until
a61af66fc99e Initial load
duke
parents:
diff changeset
5274 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
5275 max_partial_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5276 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5278 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5279
a61af66fc99e Initial load
duke
parents:
diff changeset
5280 if (min_full_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5281 return min_full_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5282 } else if (max_partial_reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5283 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5284 return max_partial_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5285 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5286 return any_reg;
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
a61af66fc99e Initial load
duke
parents:
diff changeset
5291 bool LinearScanWalker::alloc_free_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5292 TRACE_LINEAR_SCAN(2, tty->print("trying to find free register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5293
a61af66fc99e Initial load
duke
parents:
diff changeset
5294 init_use_lists(true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5295 free_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5296 free_exclude_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5297 free_collect_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5298 free_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5299 // free_collect_unhandled(fixedKind, cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5300 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
5301
a61af66fc99e Initial load
duke
parents:
diff changeset
5302 // _use_pos contains the start of the next interval that has this register assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5303 // (either as a fixed register or a normal allocated register in the past)
a61af66fc99e Initial load
duke
parents:
diff changeset
5304 // only intervals overlapping with cur are processed, non-overlapping invervals can be ignored safely
a61af66fc99e Initial load
duke
parents:
diff changeset
5305 TRACE_LINEAR_SCAN(4, tty->print_cr(" state of registers:"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5306 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
5307
a61af66fc99e Initial load
duke
parents:
diff changeset
5308 int hint_reg, hint_regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5309 Interval* register_hint = cur->register_hint();
a61af66fc99e Initial load
duke
parents:
diff changeset
5310 if (register_hint != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5311 hint_reg = register_hint->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5312 hint_regHi = register_hint->assigned_regHi();
a61af66fc99e Initial load
duke
parents:
diff changeset
5313
a61af66fc99e Initial load
duke
parents:
diff changeset
5314 if (allocator()->is_precolored_cpu_interval(register_hint)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5315 assert(hint_reg != any_reg && hint_regHi == any_reg, "must be for fixed intervals");
a61af66fc99e Initial load
duke
parents:
diff changeset
5316 hint_regHi = hint_reg + 1; // connect e.g. eax-edx
a61af66fc99e Initial load
duke
parents:
diff changeset
5317 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5318 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
5319
a61af66fc99e Initial load
duke
parents:
diff changeset
5320 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5321 hint_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5322 hint_regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5324 assert(hint_reg == any_reg || hint_reg != hint_regHi, "hint reg and regHi equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
5325 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned to interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5326
a61af66fc99e Initial load
duke
parents:
diff changeset
5327 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5328 int reg_needed_until = cur->from() + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5329 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5330
a61af66fc99e Initial load
duke
parents:
diff changeset
5331 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5332 int split_pos = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5333 int reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5334 int regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5335
a61af66fc99e Initial load
duke
parents:
diff changeset
5336 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5337 reg = find_free_double_reg(reg_needed_until, interval_to, hint_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5338 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5339 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5340 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5342 split_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5343
a61af66fc99e Initial load
duke
parents:
diff changeset
5344 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5345 reg = find_free_reg(reg_needed_until, interval_to, hint_reg, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5346 if (reg == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5347 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5349 split_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5350
a61af66fc99e Initial load
duke
parents:
diff changeset
5351 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5352 regHi = find_free_reg(reg_needed_until, interval_to, hint_regHi, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5353
a61af66fc99e Initial load
duke
parents:
diff changeset
5354 if (_use_pos[reg] < interval_to && regHi == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5355 // do not split interval if only one register can be assigned until the split pos
a61af66fc99e Initial load
duke
parents:
diff changeset
5356 // (when one register is found for the whole interval, split&spill is only
a61af66fc99e Initial load
duke
parents:
diff changeset
5357 // performed for the hi register)
a61af66fc99e Initial load
duke
parents:
diff changeset
5358 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5359
a61af66fc99e Initial load
duke
parents:
diff changeset
5360 } else if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5361 split_pos = MIN2(split_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5362
a61af66fc99e Initial load
duke
parents:
diff changeset
5363 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5364 if (reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5365 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5366 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5367 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5369 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5370 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5371 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5372
a61af66fc99e Initial load
duke
parents:
diff changeset
5373 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5374 TRACE_LINEAR_SCAN(2, tty->print_cr("selected register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5375
a61af66fc99e Initial load
duke
parents:
diff changeset
5376 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5377 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5378 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5379 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5380 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5381
a61af66fc99e Initial load
duke
parents:
diff changeset
5382 // only return true if interval is completely assigned
a61af66fc99e Initial load
duke
parents:
diff changeset
5383 return _num_phys_regs == 1 || regHi != any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5384 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5385
a61af66fc99e Initial load
duke
parents:
diff changeset
5386
a61af66fc99e Initial load
duke
parents:
diff changeset
5387 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
5388 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5389
a61af66fc99e Initial load
duke
parents:
diff changeset
5390 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5391 if (i == ignore_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5392 // this register must be ignored
a61af66fc99e Initial load
duke
parents:
diff changeset
5393
a61af66fc99e Initial load
duke
parents:
diff changeset
5394 } else if (_use_pos[i] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5395 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
5396 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5398 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5399 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5400
a61af66fc99e Initial load
duke
parents:
diff changeset
5401 if (max_reg != any_reg && _block_pos[max_reg] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5402 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5403 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5404
a61af66fc99e Initial load
duke
parents:
diff changeset
5405 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5406 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5407
a61af66fc99e Initial load
duke
parents:
diff changeset
5408 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
5409 assert((_last_reg - _first_reg + 1) % 2 == 0, "adjust algorithm");
a61af66fc99e Initial load
duke
parents:
diff changeset
5410
a61af66fc99e Initial load
duke
parents:
diff changeset
5411 int max_reg = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5412
a61af66fc99e Initial load
duke
parents:
diff changeset
5413 for (int i = _first_reg; i < _last_reg; i+=2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5414 if (_use_pos[i] > reg_needed_until && _use_pos[i + 1] > reg_needed_until) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5415 if (max_reg == any_reg || _use_pos[i] > _use_pos[max_reg]) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5416 max_reg = i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5418 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5419 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5420
a61af66fc99e Initial load
duke
parents:
diff changeset
5421 if (_block_pos[max_reg] <= interval_to || _block_pos[max_reg + 1] <= interval_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5422 *need_split = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5424
a61af66fc99e Initial load
duke
parents:
diff changeset
5425 return max_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5426 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5427
a61af66fc99e Initial load
duke
parents:
diff changeset
5428 void LinearScanWalker::split_and_spill_intersecting_intervals(int reg, int regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5429 assert(reg != any_reg, "no register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5430
a61af66fc99e Initial load
duke
parents:
diff changeset
5431 for (int i = 0; i < _spill_intervals[reg]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5432 Interval* it = _spill_intervals[reg]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5433 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5434 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5435 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5436
a61af66fc99e Initial load
duke
parents:
diff changeset
5437 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5438 IntervalList* processed = _spill_intervals[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5439 for (int i = 0; i < _spill_intervals[regHi]->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5440 Interval* it = _spill_intervals[regHi]->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5441 if (processed->index_of(it) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5442 remove_from_list(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5443 split_and_spill_interval(it);
a61af66fc99e Initial load
duke
parents:
diff changeset
5444 }
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
a61af66fc99e Initial load
duke
parents:
diff changeset
5449
a61af66fc99e Initial load
duke
parents:
diff changeset
5450 // Split an Interval and spill it to memory so that cur can be placed in a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5451 void LinearScanWalker::alloc_locked_reg(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5452 TRACE_LINEAR_SCAN(2, tty->print("need to split and spill to get register for "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5453
a61af66fc99e Initial load
duke
parents:
diff changeset
5454 // collect current usage of registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5455 init_use_lists(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5456 spill_exclude_active_fixed();
a61af66fc99e Initial load
duke
parents:
diff changeset
5457 // spill_block_unhandled_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5458 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
5459 spill_block_inactive_fixed(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5460 spill_collect_active_any();
a61af66fc99e Initial load
duke
parents:
diff changeset
5461 spill_collect_inactive_any(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5462
a61af66fc99e Initial load
duke
parents:
diff changeset
5463 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
5464 if (TraceLinearScanLevel >= 4) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5465 tty->print_cr(" state of registers:");
a61af66fc99e Initial load
duke
parents:
diff changeset
5466 for (int i = _first_reg; i <= _last_reg; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5467 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
5468 for (int j = 0; j < _spill_intervals[i]->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5469 tty->print("%d ", _spill_intervals[i]->at(j)->reg_num());
a61af66fc99e Initial load
duke
parents:
diff changeset
5470 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5471 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5473 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5474 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5475
a61af66fc99e Initial load
duke
parents:
diff changeset
5476 // the register must be free at least until this position
a61af66fc99e Initial load
duke
parents:
diff changeset
5477 int reg_needed_until = MIN2(cur->first_usage(mustHaveRegister), cur->from() + 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5478 int interval_to = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5479 assert (reg_needed_until > 0 && reg_needed_until < max_jint, "interval has no use");
a61af66fc99e Initial load
duke
parents:
diff changeset
5480
a61af66fc99e Initial load
duke
parents:
diff changeset
5481 int split_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5482 int use_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
5483 bool need_split = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5484 int reg, regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5485
a61af66fc99e Initial load
duke
parents:
diff changeset
5486 if (_adjacent_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5487 reg = find_locked_double_reg(reg_needed_until, interval_to, any_reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5488 regHi = reg + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5489
a61af66fc99e Initial load
duke
parents:
diff changeset
5490 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5491 use_pos = MIN2(_use_pos[reg], _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5492 split_pos = MIN2(_block_pos[reg], _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5493 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5494 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5495 reg = find_locked_reg(reg_needed_until, interval_to, any_reg, cur->assigned_reg(), &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5496 regHi = any_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5497
a61af66fc99e Initial load
duke
parents:
diff changeset
5498 if (reg != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5499 use_pos = _use_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5500 split_pos = _block_pos[reg];
a61af66fc99e Initial load
duke
parents:
diff changeset
5501
a61af66fc99e Initial load
duke
parents:
diff changeset
5502 if (_num_phys_regs == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5503 if (cur->assigned_reg() != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5504 regHi = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5505 reg = cur->assigned_reg();
a61af66fc99e Initial load
duke
parents:
diff changeset
5506 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5507 regHi = find_locked_reg(reg_needed_until, interval_to, any_reg, reg, &need_split);
a61af66fc99e Initial load
duke
parents:
diff changeset
5508 if (regHi != any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5509 use_pos = MIN2(use_pos, _use_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5510 split_pos = MIN2(split_pos, _block_pos[regHi]);
a61af66fc99e Initial load
duke
parents:
diff changeset
5511 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5512 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5513
a61af66fc99e Initial load
duke
parents:
diff changeset
5514 if (regHi != any_reg && reg > regHi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5515 // sort register numbers to prevent e.g. a move from eax,ebx to ebx,eax
a61af66fc99e Initial load
duke
parents:
diff changeset
5516 int temp = reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5517 reg = regHi;
a61af66fc99e Initial load
duke
parents:
diff changeset
5518 regHi = temp;
a61af66fc99e Initial load
duke
parents:
diff changeset
5519 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5520 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5521 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5522 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5523
a61af66fc99e Initial load
duke
parents:
diff changeset
5524 if (reg == any_reg || (_num_phys_regs == 2 && regHi == any_reg) || use_pos <= cur->first_usage(mustHaveRegister)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5525 // the first use of cur is later than the spilling position -> spill cur
a61af66fc99e Initial load
duke
parents:
diff changeset
5526 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
5527
a61af66fc99e Initial load
duke
parents:
diff changeset
5528 if (cur->first_usage(mustHaveRegister) <= cur->from() + 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5529 assert(false, "cannot spill interval that is used in first instruction (possible reason: no register found)");
a61af66fc99e Initial load
duke
parents:
diff changeset
5530 // assign a reasonable register and do a bailout in product mode to avoid errors
a61af66fc99e Initial load
duke
parents:
diff changeset
5531 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5532 BAILOUT("LinearScan: no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5533 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5534
a61af66fc99e Initial load
duke
parents:
diff changeset
5535 split_and_spill_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5536 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5537 TRACE_LINEAR_SCAN(4, tty->print_cr("decided to use register %d, %d", reg, regHi));
a61af66fc99e Initial load
duke
parents:
diff changeset
5538 assert(reg != any_reg && (_num_phys_regs == 1 || regHi != any_reg), "no register found");
a61af66fc99e Initial load
duke
parents:
diff changeset
5539 assert(split_pos > 0, "invalid split_pos");
a61af66fc99e Initial load
duke
parents:
diff changeset
5540 assert(need_split == false || split_pos > cur->from(), "splitting interval at from");
a61af66fc99e Initial load
duke
parents:
diff changeset
5541
a61af66fc99e Initial load
duke
parents:
diff changeset
5542 cur->assign_reg(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5543 if (need_split) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5544 // register not available for full interval, so split it
a61af66fc99e Initial load
duke
parents:
diff changeset
5545 split_when_partial_register_available(cur, split_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
5546 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5547
a61af66fc99e Initial load
duke
parents:
diff changeset
5548 // perform splitting and spilling for all affected intervalls
a61af66fc99e Initial load
duke
parents:
diff changeset
5549 split_and_spill_intersecting_intervals(reg, regHi);
a61af66fc99e Initial load
duke
parents:
diff changeset
5550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5551 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5552
a61af66fc99e Initial load
duke
parents:
diff changeset
5553 bool LinearScanWalker::no_allocation_possible(Interval* cur) {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 0
diff changeset
5554 #ifdef X86
0
a61af66fc99e Initial load
duke
parents:
diff changeset
5555 // fast calculation of intervals that can never get a register because the
a61af66fc99e Initial load
duke
parents:
diff changeset
5556 // the next instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5557 // Note: this does not work if callee-saved registers are available (e.g. on Sparc)
a61af66fc99e Initial load
duke
parents:
diff changeset
5558
a61af66fc99e Initial load
duke
parents:
diff changeset
5559 // check if this interval is the result of a split operation
a61af66fc99e Initial load
duke
parents:
diff changeset
5560 // (an interval got a register until this position)
a61af66fc99e Initial load
duke
parents:
diff changeset
5561 int pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5562 if ((pos & 1) == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5563 // the current instruction is a call that blocks all registers
a61af66fc99e Initial load
duke
parents:
diff changeset
5564 if (pos < allocator()->max_lir_op_id() && allocator()->has_call(pos + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5565 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
5566
a61af66fc99e Initial load
duke
parents:
diff changeset
5567 // safety check that there is really no register available
a61af66fc99e Initial load
duke
parents:
diff changeset
5568 assert(alloc_free_reg(cur) == false, "found a register for this interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5569 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5571
a61af66fc99e Initial load
duke
parents:
diff changeset
5572 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5573 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5574 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5576
a61af66fc99e Initial load
duke
parents:
diff changeset
5577 void LinearScanWalker::init_vars_for_alloc(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5578 BasicType type = cur->type();
a61af66fc99e Initial load
duke
parents:
diff changeset
5579 _num_phys_regs = LinearScan::num_physical_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5580 _adjacent_regs = LinearScan::requires_adjacent_regs(type);
a61af66fc99e Initial load
duke
parents:
diff changeset
5581
a61af66fc99e Initial load
duke
parents:
diff changeset
5582 if (pd_init_regs_for_alloc(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5583 // the appropriate register range was selected.
a61af66fc99e Initial load
duke
parents:
diff changeset
5584 } else if (type == T_FLOAT || type == T_DOUBLE) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5585 _first_reg = pd_first_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5586 _last_reg = pd_last_fpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5587 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5588 _first_reg = pd_first_cpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5589 _last_reg = pd_last_cpu_reg;
a61af66fc99e Initial load
duke
parents:
diff changeset
5590 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5591
a61af66fc99e Initial load
duke
parents:
diff changeset
5592 assert(0 <= _first_reg && _first_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5593 assert(0 <= _last_reg && _last_reg < LinearScan::nof_regs, "out of range");
a61af66fc99e Initial load
duke
parents:
diff changeset
5594 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5595
a61af66fc99e Initial load
duke
parents:
diff changeset
5596
a61af66fc99e Initial load
duke
parents:
diff changeset
5597 bool LinearScanWalker::is_move(LIR_Op* op, Interval* from, Interval* to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5598 if (op->code() != lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5599 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5600 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5601 assert(op->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5602
a61af66fc99e Initial load
duke
parents:
diff changeset
5603 LIR_Opr in = ((LIR_Op1*)op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5604 LIR_Opr res = ((LIR_Op1*)op)->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
5605 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
5606 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5607
a61af66fc99e Initial load
duke
parents:
diff changeset
5608 // optimization (especially for phi functions of nested loops):
a61af66fc99e Initial load
duke
parents:
diff changeset
5609 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5610 void LinearScanWalker::combine_spilled_intervals(Interval* cur) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5611 if (cur->is_split_child()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5612 // optimization is only suitable for split parents
a61af66fc99e Initial load
duke
parents:
diff changeset
5613 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5614 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5615
a61af66fc99e Initial load
duke
parents:
diff changeset
5616 Interval* register_hint = cur->register_hint(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5617 if (register_hint == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5618 // cur is not the target of a move, otherwise register_hint would be set
a61af66fc99e Initial load
duke
parents:
diff changeset
5619 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5620 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5621 assert(register_hint->is_split_parent(), "register hint must be split parent");
a61af66fc99e Initial load
duke
parents:
diff changeset
5622
a61af66fc99e Initial load
duke
parents:
diff changeset
5623 if (cur->spill_state() != noOptimization || register_hint->spill_state() != noOptimization) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5624 // combining the stack slots for intervals where spill move optimization is applied
a61af66fc99e Initial load
duke
parents:
diff changeset
5625 // is not benefitial and would cause problems
a61af66fc99e Initial load
duke
parents:
diff changeset
5626 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5627 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5628
a61af66fc99e Initial load
duke
parents:
diff changeset
5629 int begin_pos = cur->from();
a61af66fc99e Initial load
duke
parents:
diff changeset
5630 int end_pos = cur->to();
a61af66fc99e Initial load
duke
parents:
diff changeset
5631 if (end_pos > allocator()->max_lir_op_id() || (begin_pos & 1) != 0 || (end_pos & 1) != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5632 // safety check that lir_op_with_id is allowed
a61af66fc99e Initial load
duke
parents:
diff changeset
5633 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5634 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5635
a61af66fc99e Initial load
duke
parents:
diff changeset
5636 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
5637 // cur and register_hint are not connected with two moves
a61af66fc99e Initial load
duke
parents:
diff changeset
5638 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5640
a61af66fc99e Initial load
duke
parents:
diff changeset
5641 Interval* begin_hint = register_hint->split_child_at_op_id(begin_pos, LIR_OpVisitState::inputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5642 Interval* end_hint = register_hint->split_child_at_op_id(end_pos, LIR_OpVisitState::outputMode);
a61af66fc99e Initial load
duke
parents:
diff changeset
5643 if (begin_hint == end_hint || begin_hint->to() != begin_pos || end_hint->from() != end_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5644 // register_hint must be split, otherwise the re-writing of use positions does not work
a61af66fc99e Initial load
duke
parents:
diff changeset
5645 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5647
a61af66fc99e Initial load
duke
parents:
diff changeset
5648 assert(begin_hint->assigned_reg() != any_reg, "must have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5649 assert(end_hint->assigned_reg() == any_reg, "must not have register assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5650 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
5651 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
5652
a61af66fc99e Initial load
duke
parents:
diff changeset
5653 if (begin_hint->assigned_reg() < LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5654 // 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
5655 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5656 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5657 assert(register_hint->canonical_spill_slot() != -1, "must be set when part of interval was spilled");
a61af66fc99e Initial load
duke
parents:
diff changeset
5658
a61af66fc99e Initial load
duke
parents:
diff changeset
5659 // modify intervals such that cur gets the same stack slot as register_hint
a61af66fc99e Initial load
duke
parents:
diff changeset
5660 // delete use positions to prevent the intervals to get a register at beginning
a61af66fc99e Initial load
duke
parents:
diff changeset
5661 cur->set_canonical_spill_slot(register_hint->canonical_spill_slot());
a61af66fc99e Initial load
duke
parents:
diff changeset
5662 cur->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5663 end_hint->remove_first_use_pos();
a61af66fc99e Initial load
duke
parents:
diff changeset
5664 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5665
a61af66fc99e Initial load
duke
parents:
diff changeset
5666
a61af66fc99e Initial load
duke
parents:
diff changeset
5667 // allocate a physical register or memory location to an interval
a61af66fc99e Initial load
duke
parents:
diff changeset
5668 bool LinearScanWalker::activate_current() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5669 Interval* cur = current();
a61af66fc99e Initial load
duke
parents:
diff changeset
5670 bool result = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5671
a61af66fc99e Initial load
duke
parents:
diff changeset
5672 TRACE_LINEAR_SCAN(2, tty->print ("+++++ activating interval "); cur->print());
a61af66fc99e Initial load
duke
parents:
diff changeset
5673 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
5674
a61af66fc99e Initial load
duke
parents:
diff changeset
5675 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5676 // activating an interval that has a stack slot assigned -> split it at first use position
a61af66fc99e Initial load
duke
parents:
diff changeset
5677 // used for method parameters
a61af66fc99e Initial load
duke
parents:
diff changeset
5678 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
5679
a61af66fc99e Initial load
duke
parents:
diff changeset
5680 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5681 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5682
a61af66fc99e Initial load
duke
parents:
diff changeset
5683 } else if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::must_start_in_memory)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5684 // activating an interval that must start in a stack slot, but may get a register later
a61af66fc99e Initial load
duke
parents:
diff changeset
5685 // used for lir_roundfp: rounding is done by store to stack and reload later
a61af66fc99e Initial load
duke
parents:
diff changeset
5686 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
5687 assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned");
a61af66fc99e Initial load
duke
parents:
diff changeset
5688
a61af66fc99e Initial load
duke
parents:
diff changeset
5689 allocator()->assign_spill_slot(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5690 split_stack_interval(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5691 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5692
a61af66fc99e Initial load
duke
parents:
diff changeset
5693 } else if (cur->assigned_reg() == any_reg) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5694 // interval has not assigned register -> normal allocation
a61af66fc99e Initial load
duke
parents:
diff changeset
5695 // (this is the normal case for most intervals)
a61af66fc99e Initial load
duke
parents:
diff changeset
5696 TRACE_LINEAR_SCAN(4, tty->print_cr(" normal allocation of register"));
a61af66fc99e Initial load
duke
parents:
diff changeset
5697
a61af66fc99e Initial load
duke
parents:
diff changeset
5698 // assign same spill slot to non-intersecting intervals
a61af66fc99e Initial load
duke
parents:
diff changeset
5699 combine_spilled_intervals(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5700
a61af66fc99e Initial load
duke
parents:
diff changeset
5701 init_vars_for_alloc(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5702 if (no_allocation_possible(cur) || !alloc_free_reg(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5703 // no empty register available.
a61af66fc99e Initial load
duke
parents:
diff changeset
5704 // split and spill another interval so that this interval gets a register
a61af66fc99e Initial load
duke
parents:
diff changeset
5705 alloc_locked_reg(cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5707
a61af66fc99e Initial load
duke
parents:
diff changeset
5708 // spilled intervals need not be move to active-list
a61af66fc99e Initial load
duke
parents:
diff changeset
5709 if (cur->assigned_reg() >= LinearScan::nof_regs) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5710 result = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5711 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5712 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5713
a61af66fc99e Initial load
duke
parents:
diff changeset
5714 // load spilled values that become active from stack slot to register
a61af66fc99e Initial load
duke
parents:
diff changeset
5715 if (cur->insert_move_when_activated()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5716 assert(cur->is_split_child(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5717 assert(cur->current_split_child() != NULL, "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
5718 assert(cur->current_split_child()->reg_num() != cur->reg_num(), "cannot insert move between same interval");
a61af66fc99e Initial load
duke
parents:
diff changeset
5719 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
5720
a61af66fc99e Initial load
duke
parents:
diff changeset
5721 insert_move(cur->from(), cur->current_split_child(), cur);
a61af66fc99e Initial load
duke
parents:
diff changeset
5722 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5723 cur->make_current_split_child();
a61af66fc99e Initial load
duke
parents:
diff changeset
5724
a61af66fc99e Initial load
duke
parents:
diff changeset
5725 return result; // true = interval is moved to active list
a61af66fc99e Initial load
duke
parents:
diff changeset
5726 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5727
a61af66fc99e Initial load
duke
parents:
diff changeset
5728
a61af66fc99e Initial load
duke
parents:
diff changeset
5729 // Implementation of EdgeMoveOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
5730
a61af66fc99e Initial load
duke
parents:
diff changeset
5731 EdgeMoveOptimizer::EdgeMoveOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
5732 _edge_instructions(4),
a61af66fc99e Initial load
duke
parents:
diff changeset
5733 _edge_instructions_idx(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
5734 {
a61af66fc99e Initial load
duke
parents:
diff changeset
5735 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5736
a61af66fc99e Initial load
duke
parents:
diff changeset
5737 void EdgeMoveOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5738 EdgeMoveOptimizer optimizer = EdgeMoveOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
5739
a61af66fc99e Initial load
duke
parents:
diff changeset
5740 // ignore the first block in the list (index 0 is not processed)
a61af66fc99e Initial load
duke
parents:
diff changeset
5741 for (int i = code->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5742 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5743
a61af66fc99e Initial load
duke
parents:
diff changeset
5744 if (block->number_of_preds() > 1 && !block->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5745 optimizer.optimize_moves_at_block_end(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5746 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5747 if (block->number_of_sux() == 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5748 optimizer.optimize_moves_at_block_begin(block);
a61af66fc99e Initial load
duke
parents:
diff changeset
5749 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5750 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5751 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5752
a61af66fc99e Initial load
duke
parents:
diff changeset
5753
a61af66fc99e Initial load
duke
parents:
diff changeset
5754 // clear all internal data structures
a61af66fc99e Initial load
duke
parents:
diff changeset
5755 void EdgeMoveOptimizer::init_instructions() {
a61af66fc99e Initial load
duke
parents:
diff changeset
5756 _edge_instructions.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5757 _edge_instructions_idx.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
5758 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5759
a61af66fc99e Initial load
duke
parents:
diff changeset
5760 // append a lir-instruction-list and the index of the current operation in to the list
a61af66fc99e Initial load
duke
parents:
diff changeset
5761 void EdgeMoveOptimizer::append_instructions(LIR_OpList* instructions, int instructions_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5762 _edge_instructions.append(instructions);
a61af66fc99e Initial load
duke
parents:
diff changeset
5763 _edge_instructions_idx.append(instructions_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5764 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5765
a61af66fc99e Initial load
duke
parents:
diff changeset
5766 // return the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5767 LIR_Op* EdgeMoveOptimizer::instruction_at(int edge) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5768 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5769 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5770
a61af66fc99e Initial load
duke
parents:
diff changeset
5771 if (idx < instructions->length()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5772 return instructions->at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5773 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
5774 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
5775 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5776 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5777
a61af66fc99e Initial load
duke
parents:
diff changeset
5778 // removes the current operation of the given edge (predecessor or successor)
a61af66fc99e Initial load
duke
parents:
diff changeset
5779 void EdgeMoveOptimizer::remove_cur_instruction(int edge, bool decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5780 LIR_OpList* instructions = _edge_instructions.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5781 int idx = _edge_instructions_idx.at(edge);
a61af66fc99e Initial load
duke
parents:
diff changeset
5782 instructions->remove_at(idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
5783
a61af66fc99e Initial load
duke
parents:
diff changeset
5784 if (decrement_index) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5785 _edge_instructions_idx.at_put(edge, idx - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5786 }
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 bool EdgeMoveOptimizer::operations_different(LIR_Op* op1, LIR_Op* op2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5791 if (op1 == NULL || op2 == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5792 // at least one block is already empty -> no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5793 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5794 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5795
a61af66fc99e Initial load
duke
parents:
diff changeset
5796 if (op1->code() == lir_move && op2->code() == lir_move) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5797 assert(op1->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5798 assert(op2->as_Op1() != NULL, "move must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5799 LIR_Op1* move1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5800 LIR_Op1* move2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5801 if (move1->info() == move2->info() && move1->in_opr() == move2->in_opr() && move1->result_opr() == move2->result_opr()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5802 // these moves are exactly equal and can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5803 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5804 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5805
a61af66fc99e Initial load
duke
parents:
diff changeset
5806 } else if (op1->code() == lir_fxch && op2->code() == lir_fxch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5807 assert(op1->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5808 assert(op2->as_Op1() != NULL, "fxch must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
5809 LIR_Op1* fxch1 = (LIR_Op1*)op1;
a61af66fc99e Initial load
duke
parents:
diff changeset
5810 LIR_Op1* fxch2 = (LIR_Op1*)op2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5811 if (fxch1->in_opr()->as_jint() == fxch2->in_opr()->as_jint()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5812 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5813 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5814 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5815
a61af66fc99e Initial load
duke
parents:
diff changeset
5816 } else if (op1->code() == lir_fpop_raw && op2->code() == lir_fpop_raw) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5817 // equal FPU stack operations can be optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5818 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
5819 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5820
a61af66fc99e Initial load
duke
parents:
diff changeset
5821 // no optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5822 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
5823 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5824
a61af66fc99e Initial load
duke
parents:
diff changeset
5825 void EdgeMoveOptimizer::optimize_moves_at_block_end(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5826 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
5827
a61af66fc99e Initial load
duke
parents:
diff changeset
5828 if (block->is_predecessor(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5829 // currently we can't handle this correctly.
a61af66fc99e Initial load
duke
parents:
diff changeset
5830 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5831 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5832
a61af66fc99e Initial load
duke
parents:
diff changeset
5833 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5834 int num_preds = block->number_of_preds();
a61af66fc99e Initial load
duke
parents:
diff changeset
5835 assert(num_preds > 1, "do not call otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5836 assert(!block->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5837
a61af66fc99e Initial load
duke
parents:
diff changeset
5838 // setup a list with the lir-instructions of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5839 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5840 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5841 BlockBegin* pred = block->pred_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5842 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5843
a61af66fc99e Initial load
duke
parents:
diff changeset
5844 if (pred->number_of_sux() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5845 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
5846 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
5847 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5848 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5849
a61af66fc99e Initial load
duke
parents:
diff changeset
5850 assert(pred->number_of_sux() == 1, "can handle only one successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
5851 assert(pred->sux_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
5852 assert(pred_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5853 assert(pred_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5854 assert(pred_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5855
a61af66fc99e Initial load
duke
parents:
diff changeset
5856 if (pred_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5857 // can not optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5858 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5859 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5860
a61af66fc99e Initial load
duke
parents:
diff changeset
5861 // ignore the unconditional branch at the end of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
5862 append_instructions(pred_instructions, pred_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5863 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5864
a61af66fc99e Initial load
duke
parents:
diff changeset
5865
a61af66fc99e Initial load
duke
parents:
diff changeset
5866 // process lir-instructions while all predecessors end with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
5867 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5868 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
5869 for (i = 1; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5870 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5871 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
5872 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5873 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5874 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5875 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5876
a61af66fc99e Initial load
duke
parents:
diff changeset
5877 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
5878
a61af66fc99e Initial load
duke
parents:
diff changeset
5879 // insert the instruction at the beginning of the current block
a61af66fc99e Initial load
duke
parents:
diff changeset
5880 block->lir()->insert_before(1, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
5881
a61af66fc99e Initial load
duke
parents:
diff changeset
5882 // delete the instruction at the end of all predecessors
a61af66fc99e Initial load
duke
parents:
diff changeset
5883 for (i = 0; i < num_preds; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5884 remove_cur_instruction(i, true);
a61af66fc99e Initial load
duke
parents:
diff changeset
5885 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5886 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5887 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5888
a61af66fc99e Initial load
duke
parents:
diff changeset
5889
a61af66fc99e Initial load
duke
parents:
diff changeset
5890 void EdgeMoveOptimizer::optimize_moves_at_block_begin(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5891 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
5892
a61af66fc99e Initial load
duke
parents:
diff changeset
5893 init_instructions();
a61af66fc99e Initial load
duke
parents:
diff changeset
5894 int num_sux = block->number_of_sux();
a61af66fc99e Initial load
duke
parents:
diff changeset
5895
a61af66fc99e Initial load
duke
parents:
diff changeset
5896 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5897
a61af66fc99e Initial load
duke
parents:
diff changeset
5898 assert(num_sux == 2, "method should not be called otherwise");
a61af66fc99e Initial load
duke
parents:
diff changeset
5899 assert(cur_instructions->last()->code() == lir_branch, "block with successor must end with branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5900 assert(cur_instructions->last()->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5901 assert(cur_instructions->last()->as_OpBranch()->cond() == lir_cond_always, "block must end with unconditional branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
5902
a61af66fc99e Initial load
duke
parents:
diff changeset
5903 if (cur_instructions->last()->info() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5904 // can no optimize instructions when debug info is needed
a61af66fc99e Initial load
duke
parents:
diff changeset
5905 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5906 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5907
a61af66fc99e Initial load
duke
parents:
diff changeset
5908 LIR_Op* branch = cur_instructions->at(cur_instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
5909 if (branch->info() != NULL || (branch->code() != lir_branch && branch->code() != lir_cond_float_branch)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5910 // not a valid case for optimization
a61af66fc99e Initial load
duke
parents:
diff changeset
5911 // currently, only blocks that end with two branches (conditional branch followed
a61af66fc99e Initial load
duke
parents:
diff changeset
5912 // by unconditional branch) are optimized
a61af66fc99e Initial load
duke
parents:
diff changeset
5913 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5914 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5915
a61af66fc99e Initial load
duke
parents:
diff changeset
5916 // now it is guaranteed that the block ends with two branch instructions.
a61af66fc99e Initial load
duke
parents:
diff changeset
5917 // the instructions are inserted at the end of the block before these two branches
a61af66fc99e Initial load
duke
parents:
diff changeset
5918 int insert_idx = cur_instructions->length() - 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
5919
a61af66fc99e Initial load
duke
parents:
diff changeset
5920 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
5921 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
5922 for (i = insert_idx - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5923 LIR_Op* op = cur_instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5924 if ((op->code() == lir_branch || op->code() == lir_cond_float_branch) && ((LIR_OpBranch*)op)->block() != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5925 assert(false, "block with two successors can have only two branch instructions");
a61af66fc99e Initial load
duke
parents:
diff changeset
5926 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5927 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5928 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
5929
a61af66fc99e Initial load
duke
parents:
diff changeset
5930 // setup a list with the lir-instructions of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
5931 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5932 BlockBegin* sux = block->sux_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
5933 LIR_OpList* sux_instructions = sux->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
5934
a61af66fc99e Initial load
duke
parents:
diff changeset
5935 assert(sux_instructions->at(0)->code() == lir_label, "block must start with label");
a61af66fc99e Initial load
duke
parents:
diff changeset
5936
a61af66fc99e Initial load
duke
parents:
diff changeset
5937 if (sux->number_of_preds() != 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5938 // this can happen with switch-statements where multiple edges are between
a61af66fc99e Initial load
duke
parents:
diff changeset
5939 // the same blocks.
a61af66fc99e Initial load
duke
parents:
diff changeset
5940 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5941 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5942 assert(sux->pred_at(0) == block, "invalid control flow");
a61af66fc99e Initial load
duke
parents:
diff changeset
5943 assert(!sux->is_set(BlockBegin::exception_entry_flag), "exception handlers not allowed");
a61af66fc99e Initial load
duke
parents:
diff changeset
5944
a61af66fc99e Initial load
duke
parents:
diff changeset
5945 // ignore the label at the beginning of the block
a61af66fc99e Initial load
duke
parents:
diff changeset
5946 append_instructions(sux_instructions, 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
5947 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5948
a61af66fc99e Initial load
duke
parents:
diff changeset
5949 // process lir-instructions while all successors begin with the same instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
5950 while (true) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5951 LIR_Op* op = instruction_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
5952 for (i = 1; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5953 if (operations_different(op, instruction_at(i))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5954 // these instructions are different and cannot be optimized ->
a61af66fc99e Initial load
duke
parents:
diff changeset
5955 // no further optimization possible
a61af66fc99e Initial load
duke
parents:
diff changeset
5956 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
5957 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5958 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5959
a61af66fc99e Initial load
duke
parents:
diff changeset
5960 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
5961
a61af66fc99e Initial load
duke
parents:
diff changeset
5962 // insert instruction at end of current block
a61af66fc99e Initial load
duke
parents:
diff changeset
5963 block->lir()->insert_before(insert_idx, op);
a61af66fc99e Initial load
duke
parents:
diff changeset
5964 insert_idx++;
a61af66fc99e Initial load
duke
parents:
diff changeset
5965
a61af66fc99e Initial load
duke
parents:
diff changeset
5966 // delete the instructions at the beginning of all successors
a61af66fc99e Initial load
duke
parents:
diff changeset
5967 for (i = 0; i < num_sux; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5968 remove_cur_instruction(i, false);
a61af66fc99e Initial load
duke
parents:
diff changeset
5969 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5970 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5971 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5972
a61af66fc99e Initial load
duke
parents:
diff changeset
5973
a61af66fc99e Initial load
duke
parents:
diff changeset
5974 // Implementation of ControlFlowOptimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
5975
a61af66fc99e Initial load
duke
parents:
diff changeset
5976 ControlFlowOptimizer::ControlFlowOptimizer() :
a61af66fc99e Initial load
duke
parents:
diff changeset
5977 _original_preds(4)
a61af66fc99e Initial load
duke
parents:
diff changeset
5978 {
a61af66fc99e Initial load
duke
parents:
diff changeset
5979 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5980
a61af66fc99e Initial load
duke
parents:
diff changeset
5981 void ControlFlowOptimizer::optimize(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5982 ControlFlowOptimizer optimizer = ControlFlowOptimizer();
a61af66fc99e Initial load
duke
parents:
diff changeset
5983
a61af66fc99e Initial load
duke
parents:
diff changeset
5984 // push the OSR entry block to the end so that we're not jumping over it.
a61af66fc99e Initial load
duke
parents:
diff changeset
5985 BlockBegin* osr_entry = code->at(0)->end()->as_Base()->osr_entry();
a61af66fc99e Initial load
duke
parents:
diff changeset
5986 if (osr_entry) {
a61af66fc99e Initial load
duke
parents:
diff changeset
5987 int index = osr_entry->linear_scan_number();
a61af66fc99e Initial load
duke
parents:
diff changeset
5988 assert(code->at(index) == osr_entry, "wrong index");
a61af66fc99e Initial load
duke
parents:
diff changeset
5989 code->remove_at(index);
a61af66fc99e Initial load
duke
parents:
diff changeset
5990 code->append(osr_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
5991 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5992
a61af66fc99e Initial load
duke
parents:
diff changeset
5993 optimizer.reorder_short_loops(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
5994 optimizer.delete_empty_blocks(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
5995 optimizer.delete_unnecessary_jumps(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
5996 optimizer.delete_jumps_to_return(code);
a61af66fc99e Initial load
duke
parents:
diff changeset
5997 }
a61af66fc99e Initial load
duke
parents:
diff changeset
5998
a61af66fc99e Initial load
duke
parents:
diff changeset
5999 void ControlFlowOptimizer::reorder_short_loop(BlockList* code, BlockBegin* header_block, int header_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6000 int i = header_idx + 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6001 int max_end = MIN2(header_idx + ShortLoopSize, code->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
6002 while (i < max_end && code->at(i)->loop_depth() >= header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6003 i++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6004 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6005
a61af66fc99e Initial load
duke
parents:
diff changeset
6006 if (i == code->length() || code->at(i)->loop_depth() < header_block->loop_depth()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6007 int end_idx = i - 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6008 BlockBegin* end_block = code->at(end_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
6009
a61af66fc99e Initial load
duke
parents:
diff changeset
6010 if (end_block->number_of_sux() == 1 && end_block->sux_at(0) == header_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6011 // short loop from header_idx to end_idx found -> reorder blocks such that
a61af66fc99e Initial load
duke
parents:
diff changeset
6012 // the header_block is the last block instead of the first block of the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
6013 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
6014 end_idx - header_idx + 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
6015 header_block->block_id(), end_block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6016
a61af66fc99e Initial load
duke
parents:
diff changeset
6017 for (int j = header_idx; j < end_idx; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6018 code->at_put(j, code->at(j + 1));
a61af66fc99e Initial load
duke
parents:
diff changeset
6019 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6020 code->at_put(end_idx, header_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6021
a61af66fc99e Initial load
duke
parents:
diff changeset
6022 // correct the flags so that any loop alignment occurs in the right place.
a61af66fc99e Initial load
duke
parents:
diff changeset
6023 assert(code->at(end_idx)->is_set(BlockBegin::backward_branch_target_flag), "must be backward branch target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6024 code->at(end_idx)->clear(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6025 code->at(header_idx)->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6026 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6028 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6029
a61af66fc99e Initial load
duke
parents:
diff changeset
6030 void ControlFlowOptimizer::reorder_short_loops(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6031 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6032 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6033
a61af66fc99e Initial load
duke
parents:
diff changeset
6034 if (block->is_set(BlockBegin::linear_scan_loop_header_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6035 reorder_short_loop(code, block, i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6036 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6037 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6038
a61af66fc99e Initial load
duke
parents:
diff changeset
6039 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6040 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6041
a61af66fc99e Initial load
duke
parents:
diff changeset
6042 // only blocks with exactly one successor can be deleted. Such blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6043 // must always end with an unconditional branch to this successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6044 bool ControlFlowOptimizer::can_delete_block(BlockBegin* block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6045 if (block->number_of_sux() != 1 || block->number_of_exception_handlers() != 0 || block->is_entry_block()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6046 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6047 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6048
a61af66fc99e Initial load
duke
parents:
diff changeset
6049 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6050
a61af66fc99e Initial load
duke
parents:
diff changeset
6051 assert(instructions->length() >= 2, "block must have label and branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6052 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6053 assert(instructions->last()->as_OpBranch() != NULL, "last instrcution must always be a branch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6054 assert(instructions->last()->as_OpBranch()->cond() == lir_cond_always, "branch must be unconditional");
a61af66fc99e Initial load
duke
parents:
diff changeset
6055 assert(instructions->last()->as_OpBranch()->block() == block->sux_at(0), "branch target must be the successor");
a61af66fc99e Initial load
duke
parents:
diff changeset
6056
a61af66fc99e Initial load
duke
parents:
diff changeset
6057 // block must have exactly one successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6058
a61af66fc99e Initial load
duke
parents:
diff changeset
6059 if (instructions->length() == 2 && instructions->last()->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6060 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6061 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6062 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6063 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6064
a61af66fc99e Initial load
duke
parents:
diff changeset
6065 // substitute branch targets in all branch-instructions of this blocks
a61af66fc99e Initial load
duke
parents:
diff changeset
6066 void ControlFlowOptimizer::substitute_branch_target(BlockBegin* block, BlockBegin* target_from, BlockBegin* target_to) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6067 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
6068
a61af66fc99e Initial load
duke
parents:
diff changeset
6069 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6070
a61af66fc99e Initial load
duke
parents:
diff changeset
6071 assert(instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6072 for (int i = instructions->length() - 1; i >= 1; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6073 LIR_Op* op = instructions->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6074
a61af66fc99e Initial load
duke
parents:
diff changeset
6075 if (op->code() == lir_branch || op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6076 assert(op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6077 LIR_OpBranch* branch = (LIR_OpBranch*)op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6078
a61af66fc99e Initial load
duke
parents:
diff changeset
6079 if (branch->block() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6080 branch->change_block(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6081 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6082 if (branch->ublock() == target_from) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6083 branch->change_ublock(target_to);
a61af66fc99e Initial load
duke
parents:
diff changeset
6084 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6085 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6086 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6087 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6088
a61af66fc99e Initial load
duke
parents:
diff changeset
6089 void ControlFlowOptimizer::delete_empty_blocks(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6090 int old_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6091 int new_pos = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6092 int num_blocks = code->length();
a61af66fc99e Initial load
duke
parents:
diff changeset
6093
a61af66fc99e Initial load
duke
parents:
diff changeset
6094 while (old_pos < num_blocks) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6095 BlockBegin* block = code->at(old_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6096
a61af66fc99e Initial load
duke
parents:
diff changeset
6097 if (can_delete_block(block)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6098 BlockBegin* new_target = block->sux_at(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
6099
a61af66fc99e Initial load
duke
parents:
diff changeset
6100 // propagate backward branch target flag for correct code alignment
a61af66fc99e Initial load
duke
parents:
diff changeset
6101 if (block->is_set(BlockBegin::backward_branch_target_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6102 new_target->set(BlockBegin::backward_branch_target_flag);
a61af66fc99e Initial load
duke
parents:
diff changeset
6103 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6104
a61af66fc99e Initial load
duke
parents:
diff changeset
6105 // collect a list with all predecessors that contains each predecessor only once
a61af66fc99e Initial load
duke
parents:
diff changeset
6106 // the predecessors of cur are changed during the substitution, so a copy of the
a61af66fc99e Initial load
duke
parents:
diff changeset
6107 // predecessor list is necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6108 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6109 _original_preds.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6110 for (j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6111 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6112 if (_original_preds.index_of(pred) == -1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6113 _original_preds.append(pred);
a61af66fc99e Initial load
duke
parents:
diff changeset
6114 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6116
a61af66fc99e Initial load
duke
parents:
diff changeset
6117 for (j = _original_preds.length() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6118 BlockBegin* pred = _original_preds.at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6119 substitute_branch_target(pred, block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6120 pred->substitute_sux(block, new_target);
a61af66fc99e Initial load
duke
parents:
diff changeset
6121 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6122 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6123 // adjust position of this block in the block list if blocks before
a61af66fc99e Initial load
duke
parents:
diff changeset
6124 // have been deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6125 if (new_pos != old_pos) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6126 code->at_put(new_pos, code->at(old_pos));
a61af66fc99e Initial load
duke
parents:
diff changeset
6127 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6128 new_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6129 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6130 old_pos++;
a61af66fc99e Initial load
duke
parents:
diff changeset
6131 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6132 code->truncate(new_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
6133
a61af66fc99e Initial load
duke
parents:
diff changeset
6134 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6135 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6136
a61af66fc99e Initial load
duke
parents:
diff changeset
6137 void ControlFlowOptimizer::delete_unnecessary_jumps(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6138 // skip the last block because there a branch is always necessary
a61af66fc99e Initial load
duke
parents:
diff changeset
6139 for (int i = code->length() - 2; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6140 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6141 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6142
a61af66fc99e Initial load
duke
parents:
diff changeset
6143 LIR_Op* last_op = instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6144 if (last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6145 assert(last_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6146 LIR_OpBranch* last_branch = (LIR_OpBranch*)last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6147
a61af66fc99e Initial load
duke
parents:
diff changeset
6148 assert(last_branch->block() != NULL, "last branch must always have a block as target");
a61af66fc99e Initial load
duke
parents:
diff changeset
6149 assert(last_branch->label() == last_branch->block()->label(), "must be equal");
a61af66fc99e Initial load
duke
parents:
diff changeset
6150
a61af66fc99e Initial load
duke
parents:
diff changeset
6151 if (last_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6152 if (last_branch->block() == code->at(i + 1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6153
a61af66fc99e Initial load
duke
parents:
diff changeset
6154 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
6155
a61af66fc99e Initial load
duke
parents:
diff changeset
6156 // delete last branch instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6157 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6158
a61af66fc99e Initial load
duke
parents:
diff changeset
6159 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6160 LIR_Op* prev_op = instructions->at(instructions->length() - 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6161 if (prev_op->code() == lir_branch || prev_op->code() == lir_cond_float_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6162 assert(prev_op->as_OpBranch() != NULL, "branch must be of type LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6163 LIR_OpBranch* prev_branch = (LIR_OpBranch*)prev_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6164
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6165 LIR_Op2* prev_cmp = NULL;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6166
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6167 for(int j = instructions->length() - 3; j >= 0 && prev_cmp == NULL; j--) {
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6168 prev_op = instructions->at(j);
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6169 if(prev_op->code() == lir_cmp) {
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6170 assert(prev_op->as_Op2() != NULL, "branch must be of type LIR_Op2");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6171 prev_cmp = (LIR_Op2*)prev_op;
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6172 assert(prev_branch->cond() == prev_cmp->condition(), "should be the same");
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6173 }
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6174 }
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6175 assert(prev_cmp != NULL, "should have found comp instruction for branch");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6176 if (prev_branch->block() == code->at(i + 1) && prev_branch->info() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6177
a61af66fc99e Initial load
duke
parents:
diff changeset
6178 TRACE_LINEAR_SCAN(3, tty->print_cr("Negating conditional branch and deleting unconditional branch at end of block B%d", block->block_id()));
a61af66fc99e Initial load
duke
parents:
diff changeset
6179
a61af66fc99e Initial load
duke
parents:
diff changeset
6180 // eliminate a conditional branch to the immediate successor
a61af66fc99e Initial load
duke
parents:
diff changeset
6181 prev_branch->change_block(last_branch->block());
a61af66fc99e Initial load
duke
parents:
diff changeset
6182 prev_branch->negate_cond();
1681
126ea7725993 6953477: Increase portability and flexibility of building Hotspot
bobv
parents: 1584
diff changeset
6183 prev_cmp->set_condition(prev_branch->cond());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
6184 instructions->truncate(instructions->length() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
6185 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6186 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6188 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6190 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6191
a61af66fc99e Initial load
duke
parents:
diff changeset
6192 DEBUG_ONLY(verify(code));
a61af66fc99e Initial load
duke
parents:
diff changeset
6193 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6194
a61af66fc99e Initial load
duke
parents:
diff changeset
6195 void ControlFlowOptimizer::delete_jumps_to_return(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6196 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6197 BitMap return_converted(BlockBegin::number_of_blocks());
a61af66fc99e Initial load
duke
parents:
diff changeset
6198 return_converted.clear();
a61af66fc99e Initial load
duke
parents:
diff changeset
6199 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6200
a61af66fc99e Initial load
duke
parents:
diff changeset
6201 for (int i = code->length() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6202 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6203 LIR_OpList* cur_instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6204 LIR_Op* cur_last_op = cur_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6205
a61af66fc99e Initial load
duke
parents:
diff changeset
6206 assert(cur_instructions->at(0)->code() == lir_label, "first instruction must always be a label");
a61af66fc99e Initial load
duke
parents:
diff changeset
6207 if (cur_instructions->length() == 2 && cur_last_op->code() == lir_return) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6208 // the block contains only a label and a return
a61af66fc99e Initial load
duke
parents:
diff changeset
6209 // if a predecessor ends with an unconditional jump to this block, then the jump
a61af66fc99e Initial load
duke
parents:
diff changeset
6210 // can be replaced with a return instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
6211 //
a61af66fc99e Initial load
duke
parents:
diff changeset
6212 // Note: the original block with only a return statement cannot be deleted completely
a61af66fc99e Initial load
duke
parents:
diff changeset
6213 // because the predecessors might have other (conditional) jumps to this block
a61af66fc99e Initial load
duke
parents:
diff changeset
6214 // -> this may lead to unnecesary return instructions in the final code
a61af66fc99e Initial load
duke
parents:
diff changeset
6215
a61af66fc99e Initial load
duke
parents:
diff changeset
6216 assert(cur_last_op->info() == NULL, "return instructions do not have debug information");
a61af66fc99e Initial load
duke
parents:
diff changeset
6217 assert(block->number_of_sux() == 0 ||
a61af66fc99e Initial load
duke
parents:
diff changeset
6218 (return_converted.at(block->block_id()) && block->number_of_sux() == 1),
a61af66fc99e Initial load
duke
parents:
diff changeset
6219 "blocks that end with return must not have successors");
a61af66fc99e Initial load
duke
parents:
diff changeset
6220
a61af66fc99e Initial load
duke
parents:
diff changeset
6221 assert(cur_last_op->as_Op1() != NULL, "return must be LIR_Op1");
a61af66fc99e Initial load
duke
parents:
diff changeset
6222 LIR_Opr return_opr = ((LIR_Op1*)cur_last_op)->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6223
a61af66fc99e Initial load
duke
parents:
diff changeset
6224 for (int j = block->number_of_preds() - 1; j >= 0; j--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6225 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6226 LIR_OpList* pred_instructions = pred->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6227 LIR_Op* pred_last_op = pred_instructions->last();
a61af66fc99e Initial load
duke
parents:
diff changeset
6228
a61af66fc99e Initial load
duke
parents:
diff changeset
6229 if (pred_last_op->code() == lir_branch) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6230 assert(pred_last_op->as_OpBranch() != NULL, "branch must be LIR_OpBranch");
a61af66fc99e Initial load
duke
parents:
diff changeset
6231 LIR_OpBranch* pred_last_branch = (LIR_OpBranch*)pred_last_op;
a61af66fc99e Initial load
duke
parents:
diff changeset
6232
a61af66fc99e Initial load
duke
parents:
diff changeset
6233 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
6234 // replace the jump to a return with a direct return
a61af66fc99e Initial load
duke
parents:
diff changeset
6235 // Note: currently the edge between the blocks is not deleted
a61af66fc99e Initial load
duke
parents:
diff changeset
6236 pred_instructions->at_put(pred_instructions->length() - 1, new LIR_Op1(lir_return, return_opr));
a61af66fc99e Initial load
duke
parents:
diff changeset
6237 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6238 return_converted.set_bit(pred->block_id());
a61af66fc99e Initial load
duke
parents:
diff changeset
6239 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6240 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6242 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6244 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6245 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6246
a61af66fc99e Initial load
duke
parents:
diff changeset
6247
a61af66fc99e Initial load
duke
parents:
diff changeset
6248 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
6249 void ControlFlowOptimizer::verify(BlockList* code) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6250 for (int i = 0; i < code->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6251 BlockBegin* block = code->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6252 LIR_OpList* instructions = block->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6253
a61af66fc99e Initial load
duke
parents:
diff changeset
6254 int j;
a61af66fc99e Initial load
duke
parents:
diff changeset
6255 for (j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6256 LIR_OpBranch* op_branch = instructions->at(j)->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6257
a61af66fc99e Initial load
duke
parents:
diff changeset
6258 if (op_branch != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6259 assert(op_branch->block() == NULL || code->index_of(op_branch->block()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6260 assert(op_branch->ublock() == NULL || code->index_of(op_branch->ublock()) != -1, "branch target not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6261 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6262 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6263
a61af66fc99e Initial load
duke
parents:
diff changeset
6264 for (j = 0; j < block->number_of_sux() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6265 BlockBegin* sux = block->sux_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6266 assert(code->index_of(sux) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6267 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6268
a61af66fc99e Initial load
duke
parents:
diff changeset
6269 for (j = 0; j < block->number_of_preds() - 1; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6270 BlockBegin* pred = block->pred_at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6271 assert(code->index_of(pred) != -1, "successor not valid");
a61af66fc99e Initial load
duke
parents:
diff changeset
6272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6273 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6275 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
6276
a61af66fc99e Initial load
duke
parents:
diff changeset
6277
a61af66fc99e Initial load
duke
parents:
diff changeset
6278 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
6279
a61af66fc99e Initial load
duke
parents:
diff changeset
6280 // Implementation of LinearStatistic
a61af66fc99e Initial load
duke
parents:
diff changeset
6281
a61af66fc99e Initial load
duke
parents:
diff changeset
6282 const char* LinearScanStatistic::counter_name(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6283 switch (counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6284 case counter_method: return "compiled methods";
a61af66fc99e Initial load
duke
parents:
diff changeset
6285 case counter_fpu_method: return "methods using fpu";
a61af66fc99e Initial load
duke
parents:
diff changeset
6286 case counter_loop_method: return "methods with loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6287 case counter_exception_method:return "methods with xhandler";
a61af66fc99e Initial load
duke
parents:
diff changeset
6288
a61af66fc99e Initial load
duke
parents:
diff changeset
6289 case counter_loop: return "loops";
a61af66fc99e Initial load
duke
parents:
diff changeset
6290 case counter_block: return "blocks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6291 case counter_loop_block: return "blocks inside loop";
a61af66fc99e Initial load
duke
parents:
diff changeset
6292 case counter_exception_block: return "exception handler entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6293 case counter_interval: return "intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6294 case counter_fixed_interval: return "fixed intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6295 case counter_range: return "ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6296 case counter_fixed_range: return "fixed ranges";
a61af66fc99e Initial load
duke
parents:
diff changeset
6297 case counter_use_pos: return "use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6298 case counter_fixed_use_pos: return "fixed use positions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6299 case counter_spill_slots: return "spill slots";
a61af66fc99e Initial load
duke
parents:
diff changeset
6300
a61af66fc99e Initial load
duke
parents:
diff changeset
6301 // counter for classes of lir instructions
a61af66fc99e Initial load
duke
parents:
diff changeset
6302 case counter_instruction: return "total instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6303 case counter_label: return "labels";
a61af66fc99e Initial load
duke
parents:
diff changeset
6304 case counter_entry: return "method entries";
a61af66fc99e Initial load
duke
parents:
diff changeset
6305 case counter_return: return "method returns";
a61af66fc99e Initial load
duke
parents:
diff changeset
6306 case counter_call: return "method calls";
a61af66fc99e Initial load
duke
parents:
diff changeset
6307 case counter_move: return "moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6308 case counter_cmp: return "compare";
a61af66fc99e Initial load
duke
parents:
diff changeset
6309 case counter_cond_branch: return "conditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6310 case counter_uncond_branch: return "unconditional branches";
a61af66fc99e Initial load
duke
parents:
diff changeset
6311 case counter_stub_branch: return "branches to stub";
a61af66fc99e Initial load
duke
parents:
diff changeset
6312 case counter_alu: return "artithmetic + logic";
a61af66fc99e Initial load
duke
parents:
diff changeset
6313 case counter_alloc: return "allocations";
a61af66fc99e Initial load
duke
parents:
diff changeset
6314 case counter_sync: return "synchronisation";
a61af66fc99e Initial load
duke
parents:
diff changeset
6315 case counter_throw: return "throw";
a61af66fc99e Initial load
duke
parents:
diff changeset
6316 case counter_unwind: return "unwind";
a61af66fc99e Initial load
duke
parents:
diff changeset
6317 case counter_typecheck: return "type+null-checks";
a61af66fc99e Initial load
duke
parents:
diff changeset
6318 case counter_fpu_stack: return "fpu-stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6319 case counter_misc_inst: return "other instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6320 case counter_other_inst: return "misc. instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6321
a61af66fc99e Initial load
duke
parents:
diff changeset
6322 // counter for different types of moves
a61af66fc99e Initial load
duke
parents:
diff changeset
6323 case counter_move_total: return "total moves";
a61af66fc99e Initial load
duke
parents:
diff changeset
6324 case counter_move_reg_reg: return "register->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6325 case counter_move_reg_stack: return "register->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6326 case counter_move_stack_reg: return "stack->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6327 case counter_move_stack_stack:return "stack->stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6328 case counter_move_reg_mem: return "register->memory";
a61af66fc99e Initial load
duke
parents:
diff changeset
6329 case counter_move_mem_reg: return "memory->register";
a61af66fc99e Initial load
duke
parents:
diff changeset
6330 case counter_move_const_any: return "constant->any";
a61af66fc99e Initial load
duke
parents:
diff changeset
6331
a61af66fc99e Initial load
duke
parents:
diff changeset
6332 case blank_line_1: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6333 case blank_line_2: return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6334
a61af66fc99e Initial load
duke
parents:
diff changeset
6335 default: ShouldNotReachHere(); return "";
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 LinearScanStatistic::Counter LinearScanStatistic::base_counter(int counter_idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6340 if (counter_idx == counter_fpu_method || counter_idx == counter_loop_method || counter_idx == counter_exception_method) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6341 return counter_method;
a61af66fc99e Initial load
duke
parents:
diff changeset
6342 } else if (counter_idx == counter_loop_block || counter_idx == counter_exception_block) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6343 return counter_block;
a61af66fc99e Initial load
duke
parents:
diff changeset
6344 } else if (counter_idx >= counter_instruction && counter_idx <= counter_other_inst) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6345 return counter_instruction;
a61af66fc99e Initial load
duke
parents:
diff changeset
6346 } else if (counter_idx >= counter_move_total && counter_idx <= counter_move_const_any) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6347 return counter_move_total;
a61af66fc99e Initial load
duke
parents:
diff changeset
6348 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6349 return invalid_counter;
a61af66fc99e Initial load
duke
parents:
diff changeset
6350 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6351
a61af66fc99e Initial load
duke
parents:
diff changeset
6352 LinearScanStatistic::LinearScanStatistic() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6353 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6354 _counters_sum[i] = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6355 _counters_max[i] = -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
6356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6357
a61af66fc99e Initial load
duke
parents:
diff changeset
6358 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6359
a61af66fc99e Initial load
duke
parents:
diff changeset
6360 // add the method-local numbers to the total sum
a61af66fc99e Initial load
duke
parents:
diff changeset
6361 void LinearScanStatistic::sum_up(LinearScanStatistic &method_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6362 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6363 _counters_sum[i] += method_statistic._counters_sum[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
6364 _counters_max[i] = MAX2(_counters_max[i], method_statistic._counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6365 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6366 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6367
a61af66fc99e Initial load
duke
parents:
diff changeset
6368 void LinearScanStatistic::print(const char* title) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6369 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6370 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6371 tty->print_cr("***** LinearScan statistic - %s *****", title);
a61af66fc99e Initial load
duke
parents:
diff changeset
6372
a61af66fc99e Initial load
duke
parents:
diff changeset
6373 for (int i = 0; i < number_of_counters; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6374 if (_counters_sum[i] > 0 || _counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6375 tty->print("%25s: %8d", counter_name(i), _counters_sum[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6376
a61af66fc99e Initial load
duke
parents:
diff changeset
6377 if (base_counter(i) != invalid_counter) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6378 tty->print(" (%5.1f%%) ", _counters_sum[i] * 100.0 / _counters_sum[base_counter(i)]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6379 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6380 tty->print(" ");
a61af66fc99e Initial load
duke
parents:
diff changeset
6381 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6382
a61af66fc99e Initial load
duke
parents:
diff changeset
6383 if (_counters_max[i] >= 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6384 tty->print("%8d", _counters_max[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
6385 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6387 tty->cr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6388 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6389 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6390 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6391
a61af66fc99e Initial load
duke
parents:
diff changeset
6392 void LinearScanStatistic::collect(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6393 inc_counter(counter_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6394 if (allocator->has_fpu_registers()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6395 inc_counter(counter_fpu_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6396 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6397 if (allocator->num_loops() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6398 inc_counter(counter_loop_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6399 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6400 inc_counter(counter_loop, allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6401 inc_counter(counter_spill_slots, allocator->max_spills());
a61af66fc99e Initial load
duke
parents:
diff changeset
6402
a61af66fc99e Initial load
duke
parents:
diff changeset
6403 int i;
a61af66fc99e Initial load
duke
parents:
diff changeset
6404 for (i = 0; i < allocator->interval_count(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6405 Interval* cur = allocator->interval_at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6406
a61af66fc99e Initial load
duke
parents:
diff changeset
6407 if (cur != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6408 inc_counter(counter_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6409 inc_counter(counter_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6410 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6411 inc_counter(counter_fixed_interval);
a61af66fc99e Initial load
duke
parents:
diff changeset
6412 inc_counter(counter_fixed_use_pos, cur->num_use_positions());
a61af66fc99e Initial load
duke
parents:
diff changeset
6413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6414
a61af66fc99e Initial load
duke
parents:
diff changeset
6415 Range* range = cur->first();
a61af66fc99e Initial load
duke
parents:
diff changeset
6416 while (range != Range::end()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6417 inc_counter(counter_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6418 if (LinearScan::is_precolored_interval(cur)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6419 inc_counter(counter_fixed_range);
a61af66fc99e Initial load
duke
parents:
diff changeset
6420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6421 range = range->next();
a61af66fc99e Initial load
duke
parents:
diff changeset
6422 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6423 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6424 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6425
a61af66fc99e Initial load
duke
parents:
diff changeset
6426 bool has_xhandlers = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
6427 // Note: only count blocks that are in code-emit order
a61af66fc99e Initial load
duke
parents:
diff changeset
6428 for (i = 0; i < allocator->ir()->code()->length(); i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6429 BlockBegin* cur = allocator->ir()->code()->at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
6430
a61af66fc99e Initial load
duke
parents:
diff changeset
6431 inc_counter(counter_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6432 if (cur->loop_depth() > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6433 inc_counter(counter_loop_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6434 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6435 if (cur->is_set(BlockBegin::exception_entry_flag)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6436 inc_counter(counter_exception_block);
a61af66fc99e Initial load
duke
parents:
diff changeset
6437 has_xhandlers = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
6438 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6439
a61af66fc99e Initial load
duke
parents:
diff changeset
6440 LIR_OpList* instructions = cur->lir()->instructions_list();
a61af66fc99e Initial load
duke
parents:
diff changeset
6441 for (int j = 0; j < instructions->length(); j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6442 LIR_Op* op = instructions->at(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
6443
a61af66fc99e Initial load
duke
parents:
diff changeset
6444 inc_counter(counter_instruction);
a61af66fc99e Initial load
duke
parents:
diff changeset
6445
a61af66fc99e Initial load
duke
parents:
diff changeset
6446 switch (op->code()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6447 case lir_label: inc_counter(counter_label); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6448 case lir_std_entry:
a61af66fc99e Initial load
duke
parents:
diff changeset
6449 case lir_osr_entry: inc_counter(counter_entry); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6450 case lir_return: inc_counter(counter_return); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6451
a61af66fc99e Initial load
duke
parents:
diff changeset
6452 case lir_rtcall:
a61af66fc99e Initial load
duke
parents:
diff changeset
6453 case lir_static_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6454 case lir_optvirtual_call:
a61af66fc99e Initial load
duke
parents:
diff changeset
6455 case lir_virtual_call: inc_counter(counter_call); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6456
a61af66fc99e Initial load
duke
parents:
diff changeset
6457 case lir_move: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6458 inc_counter(counter_move);
a61af66fc99e Initial load
duke
parents:
diff changeset
6459 inc_counter(counter_move_total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6460
a61af66fc99e Initial load
duke
parents:
diff changeset
6461 LIR_Opr in = op->as_Op1()->in_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6462 LIR_Opr res = op->as_Op1()->result_opr();
a61af66fc99e Initial load
duke
parents:
diff changeset
6463 if (in->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6464 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6465 inc_counter(counter_move_reg_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6466 } else if (res->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6467 inc_counter(counter_move_reg_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6468 } else if (res->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6469 inc_counter(counter_move_reg_mem);
a61af66fc99e Initial load
duke
parents:
diff changeset
6470 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6471 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6473 } else if (in->is_stack()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6474 if (res->is_register()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6475 inc_counter(counter_move_stack_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6476 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6477 inc_counter(counter_move_stack_stack);
a61af66fc99e Initial load
duke
parents:
diff changeset
6478 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6479 } else if (in->is_address()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6480 assert(res->is_register(), "must be");
a61af66fc99e Initial load
duke
parents:
diff changeset
6481 inc_counter(counter_move_mem_reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
6482 } else if (in->is_constant()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6483 inc_counter(counter_move_const_any);
a61af66fc99e Initial load
duke
parents:
diff changeset
6484 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6485 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
6486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6487 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6489
a61af66fc99e Initial load
duke
parents:
diff changeset
6490 case lir_cmp: inc_counter(counter_cmp); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6491
a61af66fc99e Initial load
duke
parents:
diff changeset
6492 case lir_branch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6493 case lir_cond_float_branch: {
a61af66fc99e Initial load
duke
parents:
diff changeset
6494 LIR_OpBranch* branch = op->as_OpBranch();
a61af66fc99e Initial load
duke
parents:
diff changeset
6495 if (branch->block() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6496 inc_counter(counter_stub_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6497 } else if (branch->cond() == lir_cond_always) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6498 inc_counter(counter_uncond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6499 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
6500 inc_counter(counter_cond_branch);
a61af66fc99e Initial load
duke
parents:
diff changeset
6501 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6502 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6504
a61af66fc99e Initial load
duke
parents:
diff changeset
6505 case lir_neg:
a61af66fc99e Initial load
duke
parents:
diff changeset
6506 case lir_add:
a61af66fc99e Initial load
duke
parents:
diff changeset
6507 case lir_sub:
a61af66fc99e Initial load
duke
parents:
diff changeset
6508 case lir_mul:
a61af66fc99e Initial load
duke
parents:
diff changeset
6509 case lir_mul_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6510 case lir_div:
a61af66fc99e Initial load
duke
parents:
diff changeset
6511 case lir_div_strictfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6512 case lir_rem:
a61af66fc99e Initial load
duke
parents:
diff changeset
6513 case lir_sqrt:
a61af66fc99e Initial load
duke
parents:
diff changeset
6514 case lir_sin:
a61af66fc99e Initial load
duke
parents:
diff changeset
6515 case lir_cos:
a61af66fc99e Initial load
duke
parents:
diff changeset
6516 case lir_abs:
a61af66fc99e Initial load
duke
parents:
diff changeset
6517 case lir_log10:
a61af66fc99e Initial load
duke
parents:
diff changeset
6518 case lir_log:
a61af66fc99e Initial load
duke
parents:
diff changeset
6519 case lir_logic_and:
a61af66fc99e Initial load
duke
parents:
diff changeset
6520 case lir_logic_or:
a61af66fc99e Initial load
duke
parents:
diff changeset
6521 case lir_logic_xor:
a61af66fc99e Initial load
duke
parents:
diff changeset
6522 case lir_shl:
a61af66fc99e Initial load
duke
parents:
diff changeset
6523 case lir_shr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6524 case lir_ushr: inc_counter(counter_alu); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6525
a61af66fc99e Initial load
duke
parents:
diff changeset
6526 case lir_alloc_object:
a61af66fc99e Initial load
duke
parents:
diff changeset
6527 case lir_alloc_array: inc_counter(counter_alloc); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6528
a61af66fc99e Initial load
duke
parents:
diff changeset
6529 case lir_monaddr:
a61af66fc99e Initial load
duke
parents:
diff changeset
6530 case lir_lock:
a61af66fc99e Initial load
duke
parents:
diff changeset
6531 case lir_unlock: inc_counter(counter_sync); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6532
a61af66fc99e Initial load
duke
parents:
diff changeset
6533 case lir_throw: inc_counter(counter_throw); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6534
a61af66fc99e Initial load
duke
parents:
diff changeset
6535 case lir_unwind: inc_counter(counter_unwind); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6536
a61af66fc99e Initial load
duke
parents:
diff changeset
6537 case lir_null_check:
a61af66fc99e Initial load
duke
parents:
diff changeset
6538 case lir_leal:
a61af66fc99e Initial load
duke
parents:
diff changeset
6539 case lir_instanceof:
a61af66fc99e Initial load
duke
parents:
diff changeset
6540 case lir_checkcast:
a61af66fc99e Initial load
duke
parents:
diff changeset
6541 case lir_store_check: inc_counter(counter_typecheck); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6542
a61af66fc99e Initial load
duke
parents:
diff changeset
6543 case lir_fpop_raw:
a61af66fc99e Initial load
duke
parents:
diff changeset
6544 case lir_fxch:
a61af66fc99e Initial load
duke
parents:
diff changeset
6545 case lir_fld: inc_counter(counter_fpu_stack); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6546
a61af66fc99e Initial load
duke
parents:
diff changeset
6547 case lir_nop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6548 case lir_push:
a61af66fc99e Initial load
duke
parents:
diff changeset
6549 case lir_pop:
a61af66fc99e Initial load
duke
parents:
diff changeset
6550 case lir_convert:
a61af66fc99e Initial load
duke
parents:
diff changeset
6551 case lir_roundfp:
a61af66fc99e Initial load
duke
parents:
diff changeset
6552 case lir_cmove: inc_counter(counter_misc_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6553
a61af66fc99e Initial load
duke
parents:
diff changeset
6554 default: inc_counter(counter_other_inst); break;
a61af66fc99e Initial load
duke
parents:
diff changeset
6555 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6556 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6557 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6558
a61af66fc99e Initial load
duke
parents:
diff changeset
6559 if (has_xhandlers) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6560 inc_counter(counter_exception_method);
a61af66fc99e Initial load
duke
parents:
diff changeset
6561 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6562 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6563
a61af66fc99e Initial load
duke
parents:
diff changeset
6564 void LinearScanStatistic::compute(LinearScan* allocator, LinearScanStatistic &global_statistic) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6565 if (CountLinearScan || TraceLinearScanLevel > 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6566
a61af66fc99e Initial load
duke
parents:
diff changeset
6567 LinearScanStatistic local_statistic = LinearScanStatistic();
a61af66fc99e Initial load
duke
parents:
diff changeset
6568
a61af66fc99e Initial load
duke
parents:
diff changeset
6569 local_statistic.collect(allocator);
a61af66fc99e Initial load
duke
parents:
diff changeset
6570 global_statistic.sum_up(local_statistic);
a61af66fc99e Initial load
duke
parents:
diff changeset
6571
a61af66fc99e Initial load
duke
parents:
diff changeset
6572 if (TraceLinearScanLevel > 2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6573 local_statistic.print("current local statistic");
a61af66fc99e Initial load
duke
parents:
diff changeset
6574 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6575 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6576 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6577
a61af66fc99e Initial load
duke
parents:
diff changeset
6578
a61af66fc99e Initial load
duke
parents:
diff changeset
6579 // Implementation of LinearTimers
a61af66fc99e Initial load
duke
parents:
diff changeset
6580
a61af66fc99e Initial load
duke
parents:
diff changeset
6581 LinearScanTimers::LinearScanTimers() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6582 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6583 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6584 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6585 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6586
a61af66fc99e Initial load
duke
parents:
diff changeset
6587 const char* LinearScanTimers::timer_name(int idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6588 switch (idx) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6589 case timer_do_nothing: return "Nothing (Time Check)";
a61af66fc99e Initial load
duke
parents:
diff changeset
6590 case timer_number_instructions: return "Number Instructions";
a61af66fc99e Initial load
duke
parents:
diff changeset
6591 case timer_compute_local_live_sets: return "Local Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6592 case timer_compute_global_live_sets: return "Global Live Sets";
a61af66fc99e Initial load
duke
parents:
diff changeset
6593 case timer_build_intervals: return "Build Intervals";
a61af66fc99e Initial load
duke
parents:
diff changeset
6594 case timer_sort_intervals_before: return "Sort Intervals Before";
a61af66fc99e Initial load
duke
parents:
diff changeset
6595 case timer_allocate_registers: return "Allocate Registers";
a61af66fc99e Initial load
duke
parents:
diff changeset
6596 case timer_resolve_data_flow: return "Resolve Data Flow";
a61af66fc99e Initial load
duke
parents:
diff changeset
6597 case timer_sort_intervals_after: return "Sort Intervals After";
a61af66fc99e Initial load
duke
parents:
diff changeset
6598 case timer_eliminate_spill_moves: return "Spill optimization";
a61af66fc99e Initial load
duke
parents:
diff changeset
6599 case timer_assign_reg_num: return "Assign Reg Num";
a61af66fc99e Initial load
duke
parents:
diff changeset
6600 case timer_allocate_fpu_stack: return "Allocate FPU Stack";
a61af66fc99e Initial load
duke
parents:
diff changeset
6601 case timer_optimize_lir: return "Optimize LIR";
a61af66fc99e Initial load
duke
parents:
diff changeset
6602 default: ShouldNotReachHere(); return "";
a61af66fc99e Initial load
duke
parents:
diff changeset
6603 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6604 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6605
a61af66fc99e Initial load
duke
parents:
diff changeset
6606 void LinearScanTimers::begin_method() {
a61af66fc99e Initial load
duke
parents:
diff changeset
6607 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6608 // reset all timers to measure only current method
a61af66fc99e Initial load
duke
parents:
diff changeset
6609 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6610 timer(i)->reset();
a61af66fc99e Initial load
duke
parents:
diff changeset
6611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6612 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6613 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6614
a61af66fc99e Initial load
duke
parents:
diff changeset
6615 void LinearScanTimers::end_method(LinearScan* allocator) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6616 if (TimeEachLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6617
a61af66fc99e Initial load
duke
parents:
diff changeset
6618 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6619 double total = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
6620 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6621 total += timer(i)->seconds() - c;
a61af66fc99e Initial load
duke
parents:
diff changeset
6622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6623
a61af66fc99e Initial load
duke
parents:
diff changeset
6624 if (total >= 0.0005) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6625 // print all information in one line for automatic processing
a61af66fc99e Initial load
duke
parents:
diff changeset
6626 tty->print("@"); allocator->compilation()->method()->print_name();
a61af66fc99e Initial load
duke
parents:
diff changeset
6627
a61af66fc99e Initial load
duke
parents:
diff changeset
6628 tty->print("@ %d ", allocator->compilation()->method()->code_size());
a61af66fc99e Initial load
duke
parents:
diff changeset
6629 tty->print("@ %d ", allocator->block_at(allocator->block_count() - 1)->last_lir_instruction_id() / 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
6630 tty->print("@ %d ", allocator->block_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6631 tty->print("@ %d ", allocator->num_virtual_regs());
a61af66fc99e Initial load
duke
parents:
diff changeset
6632 tty->print("@ %d ", allocator->interval_count());
a61af66fc99e Initial load
duke
parents:
diff changeset
6633 tty->print("@ %d ", allocator->_num_calls);
a61af66fc99e Initial load
duke
parents:
diff changeset
6634 tty->print("@ %d ", allocator->num_loops());
a61af66fc99e Initial load
duke
parents:
diff changeset
6635
a61af66fc99e Initial load
duke
parents:
diff changeset
6636 tty->print("@ %6.6f ", total);
a61af66fc99e Initial load
duke
parents:
diff changeset
6637 for (int i = 1; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6638 tty->print("@ %4.1f ", ((timer(i)->seconds() - c) / total) * 100);
a61af66fc99e Initial load
duke
parents:
diff changeset
6639 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6640 tty->cr();
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 void LinearScanTimers::print(double total_time) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6646 if (TimeLinearScan) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6647 // correction value: sum of dummy-timer that only measures the time that
a61af66fc99e Initial load
duke
parents:
diff changeset
6648 // is necesary to start and stop itself
a61af66fc99e Initial load
duke
parents:
diff changeset
6649 double c = timer(timer_do_nothing)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6650
a61af66fc99e Initial load
duke
parents:
diff changeset
6651 for (int i = 0; i < number_of_timers; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
6652 double t = timer(i)->seconds();
a61af66fc99e Initial load
duke
parents:
diff changeset
6653 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
6654 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6655 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6656 }
a61af66fc99e Initial load
duke
parents:
diff changeset
6657
a61af66fc99e Initial load
duke
parents:
diff changeset
6658 #endif // #ifndef PRODUCT