Mercurial > hg > truffle
annotate src/share/vm/opto/lcm.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 | 6c9cc03d8726 |
children | 3e8fbc61cee8 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1151
diff
changeset
|
2 * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1151
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1151
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:
1151
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 // Optimization - Graph Style | |
26 | |
27 #include "incls/_precompiled.incl" | |
28 #include "incls/_lcm.cpp.incl" | |
29 | |
30 //------------------------------implicit_null_check---------------------------- | |
31 // Detect implicit-null-check opportunities. Basically, find NULL checks | |
32 // with suitable memory ops nearby. Use the memory op to do the NULL check. | |
33 // I can generate a memory op if there is not one nearby. | |
34 // The proj is the control projection for the not-null case. | |
1575
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
35 // The val is the pointer being checked for nullness or |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
36 // decodeHeapOop_not_null node if it did not fold into address. |
0 | 37 void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowed_reasons) { |
38 // Assume if null check need for 0 offset then always needed | |
39 // Intel solaris doesn't support any null checks yet and no | |
40 // mechanism exists (yet) to set the switches at an os_cpu level | |
41 if( !ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(0)) return; | |
42 | |
43 // Make sure the ptr-is-null path appears to be uncommon! | |
44 float f = end()->as_MachIf()->_prob; | |
45 if( proj->Opcode() == Op_IfTrue ) f = 1.0f - f; | |
46 if( f > PROB_UNLIKELY_MAG(4) ) return; | |
47 | |
48 uint bidx = 0; // Capture index of value into memop | |
49 bool was_store; // Memory op is a store op | |
50 | |
51 // Get the successor block for if the test ptr is non-null | |
52 Block* not_null_block; // this one goes with the proj | |
53 Block* null_block; | |
54 if (_nodes[_nodes.size()-1] == proj) { | |
55 null_block = _succs[0]; | |
56 not_null_block = _succs[1]; | |
57 } else { | |
58 assert(_nodes[_nodes.size()-2] == proj, "proj is one or the other"); | |
59 not_null_block = _succs[0]; | |
60 null_block = _succs[1]; | |
61 } | |
332 | 62 while (null_block->is_Empty() == Block::empty_with_goto) { |
63 null_block = null_block->_succs[0]; | |
64 } | |
0 | 65 |
66 // Search the exception block for an uncommon trap. | |
67 // (See Parse::do_if and Parse::do_ifnull for the reason | |
68 // we need an uncommon trap. Briefly, we need a way to | |
69 // detect failure of this optimization, as in 6366351.) | |
70 { | |
71 bool found_trap = false; | |
72 for (uint i1 = 0; i1 < null_block->_nodes.size(); i1++) { | |
73 Node* nn = null_block->_nodes[i1]; | |
74 if (nn->is_MachCall() && | |
75 nn->as_MachCall()->entry_point() == | |
76 SharedRuntime::uncommon_trap_blob()->instructions_begin()) { | |
77 const Type* trtype = nn->in(TypeFunc::Parms)->bottom_type(); | |
78 if (trtype->isa_int() && trtype->is_int()->is_con()) { | |
79 jint tr_con = trtype->is_int()->get_con(); | |
80 Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(tr_con); | |
81 Deoptimization::DeoptAction action = Deoptimization::trap_request_action(tr_con); | |
82 assert((int)reason < (int)BitsPerInt, "recode bit map"); | |
83 if (is_set_nth_bit(allowed_reasons, (int) reason) | |
84 && action != Deoptimization::Action_none) { | |
85 // This uncommon trap is sure to recompile, eventually. | |
86 // When that happens, C->too_many_traps will prevent | |
87 // this transformation from happening again. | |
88 found_trap = true; | |
89 } | |
90 } | |
91 break; | |
92 } | |
93 } | |
94 if (!found_trap) { | |
95 // We did not find an uncommon trap. | |
96 return; | |
97 } | |
98 } | |
99 | |
1575
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
100 // Check for decodeHeapOop_not_null node which did not fold into address |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
101 bool is_decoden = ((intptr_t)val) & 1; |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
102 val = (Node*)(((intptr_t)val) & ~1); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
103 |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
104 assert(!is_decoden || (val->in(0) == NULL) && val->is_Mach() && |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
105 (val->as_Mach()->ideal_Opcode() == Op_DecodeN), "sanity"); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
106 |
0 | 107 // Search the successor block for a load or store who's base value is also |
108 // the tested value. There may be several. | |
109 Node_List *out = new Node_List(Thread::current()->resource_area()); | |
110 MachNode *best = NULL; // Best found so far | |
111 for (DUIterator i = val->outs(); val->has_out(i); i++) { | |
112 Node *m = val->out(i); | |
113 if( !m->is_Mach() ) continue; | |
114 MachNode *mach = m->as_Mach(); | |
115 was_store = false; | |
1693
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
116 int iop = mach->ideal_Opcode(); |
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
117 switch( iop ) { |
0 | 118 case Op_LoadB: |
558
3b5ac9e7e6ea
6796746: rename LoadC (char) opcode class to LoadUS (unsigned short)
twisti
parents:
365
diff
changeset
|
119 case Op_LoadUS: |
0 | 120 case Op_LoadD: |
121 case Op_LoadF: | |
122 case Op_LoadI: | |
123 case Op_LoadL: | |
124 case Op_LoadP: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
125 case Op_LoadN: |
0 | 126 case Op_LoadS: |
127 case Op_LoadKlass: | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
125
diff
changeset
|
128 case Op_LoadNKlass: |
0 | 129 case Op_LoadRange: |
130 case Op_LoadD_unaligned: | |
131 case Op_LoadL_unaligned: | |
1151
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
132 assert(mach->in(2) == val, "should be address"); |
0 | 133 break; |
134 case Op_StoreB: | |
135 case Op_StoreC: | |
136 case Op_StoreCM: | |
137 case Op_StoreD: | |
138 case Op_StoreF: | |
139 case Op_StoreI: | |
140 case Op_StoreL: | |
141 case Op_StoreP: | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
142 case Op_StoreN: |
0 | 143 was_store = true; // Memory op is a store op |
144 // Stores will have their address in slot 2 (memory in slot 1). | |
145 // If the value being nul-checked is in another slot, it means we | |
146 // are storing the checked value, which does NOT check the value! | |
147 if( mach->in(2) != val ) continue; | |
148 break; // Found a memory op? | |
149 case Op_StrComp: | |
681 | 150 case Op_StrEquals: |
151 case Op_StrIndexOf: | |
169
9148c65abefc
6695049: (coll) Create an x86 intrinsic for Arrays.equals
rasbold
parents:
164
diff
changeset
|
152 case Op_AryEq: |
0 | 153 // Not a legit memory op for implicit null check regardless of |
154 // embedded loads | |
155 continue; | |
156 default: // Also check for embedded loads | |
157 if( !mach->needs_anti_dependence_check() ) | |
158 continue; // Not an memory op; skip it | |
1693
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
159 if( must_clone[iop] ) { |
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
160 // Do not move nodes which produce flags because |
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
161 // RA will try to clone it to place near branch and |
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
162 // it will cause recompilation, see clone_node(). |
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
163 continue; |
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
164 } |
1151
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
165 { |
1575
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
166 // Check that value is used in memory address in |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
167 // instructions with embedded load (CmpP val1,(val2+off)). |
1151
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
168 Node* base; |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
169 Node* index; |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
170 const MachOper* oper = mach->memory_inputs(base, index); |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
171 if (oper == NULL || oper == (MachOper*)-1) { |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
172 continue; // Not an memory op; skip it |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
173 } |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
174 if (val == base || |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
175 val == index && val->bottom_type()->isa_narrowoop()) { |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
176 break; // Found it |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
177 } else { |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
178 continue; // Skip it |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
179 } |
1271af4ec18c
6912517: JIT bug compiles out (and stops running) code that needs to be run. Causes NPE.
kvn
parents:
1137
diff
changeset
|
180 } |
0 | 181 break; |
182 } | |
183 // check if the offset is not too high for implicit exception | |
184 { | |
185 intptr_t offset = 0; | |
186 const TypePtr *adr_type = NULL; // Do not need this return value here | |
187 const Node* base = mach->get_base_and_disp(offset, adr_type); | |
188 if (base == NULL || base == NodeSentinel) { | |
332 | 189 // Narrow oop address doesn't have base, only index |
190 if( val->bottom_type()->isa_narrowoop() && | |
191 MacroAssembler::needs_explicit_null_check(offset) ) | |
192 continue; // Give up if offset is beyond page size | |
0 | 193 // cannot reason about it; is probably not implicit null exception |
194 } else { | |
642
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
195 const TypePtr* tptr; |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
196 if (UseCompressedOops && Universe::narrow_oop_shift() == 0) { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
197 // 32-bits narrow oop can be the base of address expressions |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
198 tptr = base->bottom_type()->make_ptr(); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
199 } else { |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
200 // only regular oops are expected here |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
201 tptr = base->bottom_type()->is_ptr(); |
660978a2a31a
6791178: Specialize for zero as the compressed oop vm heap base
kvn
parents:
558
diff
changeset
|
202 } |
0 | 203 // Give up if offset is not a compile-time constant |
204 if( offset == Type::OffsetBot || tptr->_offset == Type::OffsetBot ) | |
205 continue; | |
206 offset += tptr->_offset; // correct if base is offseted | |
207 if( MacroAssembler::needs_explicit_null_check(offset) ) | |
208 continue; // Give up is reference is beyond 4K page size | |
209 } | |
210 } | |
211 | |
212 // Check ctrl input to see if the null-check dominates the memory op | |
213 Block *cb = cfg->_bbs[mach->_idx]; | |
214 cb = cb->_idom; // Always hoist at least 1 block | |
215 if( !was_store ) { // Stores can be hoisted only one block | |
216 while( cb->_dom_depth > (_dom_depth + 1)) | |
217 cb = cb->_idom; // Hoist loads as far as we want | |
218 // The non-null-block should dominate the memory op, too. Live | |
219 // range spilling will insert a spill in the non-null-block if it is | |
220 // needs to spill the memory op for an implicit null check. | |
221 if (cb->_dom_depth == (_dom_depth + 1)) { | |
222 if (cb != not_null_block) continue; | |
223 cb = cb->_idom; | |
224 } | |
225 } | |
226 if( cb != this ) continue; | |
227 | |
228 // Found a memory user; see if it can be hoisted to check-block | |
229 uint vidx = 0; // Capture index of value into memop | |
230 uint j; | |
231 for( j = mach->req()-1; j > 0; j-- ) { | |
1575
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
232 if( mach->in(j) == val ) { |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
233 vidx = j; |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
234 // Ignore DecodeN val which could be hoisted to where needed. |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
235 if( is_decoden ) continue; |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
236 } |
0 | 237 // Block of memory-op input |
238 Block *inb = cfg->_bbs[mach->in(j)->_idx]; | |
239 Block *b = this; // Start from nul check | |
240 while( b != inb && b->_dom_depth > inb->_dom_depth ) | |
241 b = b->_idom; // search upwards for input | |
242 // See if input dominates null check | |
243 if( b != inb ) | |
244 break; | |
245 } | |
246 if( j > 0 ) | |
247 continue; | |
248 Block *mb = cfg->_bbs[mach->_idx]; | |
249 // Hoisting stores requires more checks for the anti-dependence case. | |
250 // Give up hoisting if we have to move the store past any load. | |
251 if( was_store ) { | |
252 Block *b = mb; // Start searching here for a local load | |
253 // mach use (faulting) trying to hoist | |
254 // n might be blocker to hoisting | |
255 while( b != this ) { | |
256 uint k; | |
257 for( k = 1; k < b->_nodes.size(); k++ ) { | |
258 Node *n = b->_nodes[k]; | |
259 if( n->needs_anti_dependence_check() && | |
260 n->in(LoadNode::Memory) == mach->in(StoreNode::Memory) ) | |
261 break; // Found anti-dependent load | |
262 } | |
263 if( k < b->_nodes.size() ) | |
264 break; // Found anti-dependent load | |
265 // Make sure control does not do a merge (would have to check allpaths) | |
266 if( b->num_preds() != 2 ) break; | |
267 b = cfg->_bbs[b->pred(1)->_idx]; // Move up to predecessor block | |
268 } | |
269 if( b != this ) continue; | |
270 } | |
271 | |
272 // Make sure this memory op is not already being used for a NullCheck | |
273 Node *e = mb->end(); | |
274 if( e->is_MachNullCheck() && e->in(1) == mach ) | |
275 continue; // Already being used as a NULL check | |
276 | |
277 // Found a candidate! Pick one with least dom depth - the highest | |
278 // in the dom tree should be closest to the null check. | |
279 if( !best || | |
280 cfg->_bbs[mach->_idx]->_dom_depth < cfg->_bbs[best->_idx]->_dom_depth ) { | |
281 best = mach; | |
282 bidx = vidx; | |
283 | |
284 } | |
285 } | |
286 // No candidate! | |
287 if( !best ) return; | |
288 | |
289 // ---- Found an implicit null check | |
290 extern int implicit_null_checks; | |
291 implicit_null_checks++; | |
292 | |
1575
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
293 if( is_decoden ) { |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
294 // Check if we need to hoist decodeHeapOop_not_null first. |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
295 Block *valb = cfg->_bbs[val->_idx]; |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
296 if( this != valb && this->_dom_depth < valb->_dom_depth ) { |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
297 // Hoist it up to the end of the test block. |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
298 valb->find_remove(val); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
299 this->add_inst(val); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
300 cfg->_bbs.map(val->_idx,this); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
301 // DecodeN on x86 may kill flags. Check for flag-killing projections |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
302 // that also need to be hoisted. |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
303 for (DUIterator_Fast jmax, j = val->fast_outs(jmax); j < jmax; j++) { |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
304 Node* n = val->fast_out(j); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
305 if( n->Opcode() == Op_MachProj ) { |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
306 cfg->_bbs[n->_idx]->find_remove(n); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
307 this->add_inst(n); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
308 cfg->_bbs.map(n->_idx,this); |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
309 } |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
310 } |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
311 } |
3657cb01ffc5
6954029: Improve implicit null check generation with compressed oops
kvn
parents:
1151
diff
changeset
|
312 } |
0 | 313 // Hoist the memory candidate up to the end of the test block. |
314 Block *old_block = cfg->_bbs[best->_idx]; | |
315 old_block->find_remove(best); | |
316 add_inst(best); | |
317 cfg->_bbs.map(best->_idx,this); | |
318 | |
319 // Move the control dependence | |
320 if (best->in(0) && best->in(0) == old_block->_nodes[0]) | |
321 best->set_req(0, _nodes[0]); | |
322 | |
323 // Check for flag-killing projections that also need to be hoisted | |
324 // Should be DU safe because no edge updates. | |
325 for (DUIterator_Fast jmax, j = best->fast_outs(jmax); j < jmax; j++) { | |
326 Node* n = best->fast_out(j); | |
327 if( n->Opcode() == Op_MachProj ) { | |
328 cfg->_bbs[n->_idx]->find_remove(n); | |
329 add_inst(n); | |
330 cfg->_bbs.map(n->_idx,this); | |
331 } | |
332 } | |
333 | |
334 Compile *C = cfg->C; | |
335 // proj==Op_True --> ne test; proj==Op_False --> eq test. | |
336 // One of two graph shapes got matched: | |
337 // (IfTrue (If (Bool NE (CmpP ptr NULL)))) | |
338 // (IfFalse (If (Bool EQ (CmpP ptr NULL)))) | |
339 // NULL checks are always branch-if-eq. If we see a IfTrue projection | |
340 // then we are replacing a 'ne' test with a 'eq' NULL check test. | |
341 // We need to flip the projections to keep the same semantics. | |
342 if( proj->Opcode() == Op_IfTrue ) { | |
343 // Swap order of projections in basic block to swap branch targets | |
344 Node *tmp1 = _nodes[end_idx()+1]; | |
345 Node *tmp2 = _nodes[end_idx()+2]; | |
346 _nodes.map(end_idx()+1, tmp2); | |
347 _nodes.map(end_idx()+2, tmp1); | |
348 Node *tmp = new (C, 1) Node(C->top()); // Use not NULL input | |
349 tmp1->replace_by(tmp); | |
350 tmp2->replace_by(tmp1); | |
351 tmp->replace_by(tmp2); | |
352 tmp->destruct(); | |
353 } | |
354 | |
355 // Remove the existing null check; use a new implicit null check instead. | |
356 // Since schedule-local needs precise def-use info, we need to correct | |
357 // it as well. | |
358 Node *old_tst = proj->in(0); | |
359 MachNode *nul_chk = new (C) MachNullCheckNode(old_tst->in(0),best,bidx); | |
360 _nodes.map(end_idx(),nul_chk); | |
361 cfg->_bbs.map(nul_chk->_idx,this); | |
362 // Redirect users of old_test to nul_chk | |
363 for (DUIterator_Last i2min, i2 = old_tst->last_outs(i2min); i2 >= i2min; --i2) | |
364 old_tst->last_out(i2)->set_req(0, nul_chk); | |
365 // Clean-up any dead code | |
366 for (uint i3 = 0; i3 < old_tst->req(); i3++) | |
367 old_tst->set_req(i3, NULL); | |
368 | |
369 cfg->latency_from_uses(nul_chk); | |
370 cfg->latency_from_uses(best); | |
371 } | |
372 | |
373 | |
374 //------------------------------select----------------------------------------- | |
375 // Select a nice fellow from the worklist to schedule next. If there is only | |
376 // one choice, then use it. Projections take top priority for correctness | |
377 // reasons - if I see a projection, then it is next. There are a number of | |
378 // other special cases, for instructions that consume condition codes, et al. | |
379 // These are chosen immediately. Some instructions are required to immediately | |
380 // precede the last instruction in the block, and these are taken last. Of the | |
381 // remaining cases (most), choose the instruction with the greatest latency | |
382 // (that is, the most number of pseudo-cycles required to the end of the | |
383 // routine). If there is a tie, choose the instruction with the most inputs. | |
384 Node *Block::select(PhaseCFG *cfg, Node_List &worklist, int *ready_cnt, VectorSet &next_call, uint sched_slot) { | |
385 | |
386 // If only a single entry on the stack, use it | |
387 uint cnt = worklist.size(); | |
388 if (cnt == 1) { | |
389 Node *n = worklist[0]; | |
390 worklist.map(0,worklist.pop()); | |
391 return n; | |
392 } | |
393 | |
394 uint choice = 0; // Bigger is most important | |
395 uint latency = 0; // Bigger is scheduled first | |
396 uint score = 0; // Bigger is better | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
397 int idx = -1; // Index in worklist |
0 | 398 |
399 for( uint i=0; i<cnt; i++ ) { // Inspect entire worklist | |
400 // Order in worklist is used to break ties. | |
401 // See caller for how this is used to delay scheduling | |
402 // of induction variable increments to after the other | |
403 // uses of the phi are scheduled. | |
404 Node *n = worklist[i]; // Get Node on worklist | |
405 | |
406 int iop = n->is_Mach() ? n->as_Mach()->ideal_Opcode() : 0; | |
407 if( n->is_Proj() || // Projections always win | |
408 n->Opcode()== Op_Con || // So does constant 'Top' | |
409 iop == Op_CreateEx || // Create-exception must start block | |
410 iop == Op_CheckCastPP | |
411 ) { | |
412 worklist.map(i,worklist.pop()); | |
413 return n; | |
414 } | |
415 | |
416 // Final call in a block must be adjacent to 'catch' | |
417 Node *e = end(); | |
418 if( e->is_Catch() && e->in(0)->in(0) == n ) | |
419 continue; | |
420 | |
421 // Memory op for an implicit null check has to be at the end of the block | |
422 if( e->is_MachNullCheck() && e->in(1) == n ) | |
423 continue; | |
424 | |
425 uint n_choice = 2; | |
426 | |
427 // See if this instruction is consumed by a branch. If so, then (as the | |
428 // branch is the last instruction in the basic block) force it to the | |
429 // end of the basic block | |
430 if ( must_clone[iop] ) { | |
431 // See if any use is a branch | |
432 bool found_machif = false; | |
433 | |
434 for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | |
435 Node* use = n->fast_out(j); | |
436 | |
437 // The use is a conditional branch, make them adjacent | |
438 if (use->is_MachIf() && cfg->_bbs[use->_idx]==this ) { | |
439 found_machif = true; | |
440 break; | |
441 } | |
442 | |
443 // More than this instruction pending for successor to be ready, | |
444 // don't choose this if other opportunities are ready | |
445 if (ready_cnt[use->_idx] > 1) | |
446 n_choice = 1; | |
447 } | |
448 | |
449 // loop terminated, prefer not to use this instruction | |
450 if (found_machif) | |
451 continue; | |
452 } | |
453 | |
454 // See if this has a predecessor that is "must_clone", i.e. sets the | |
455 // condition code. If so, choose this first | |
456 for (uint j = 0; j < n->req() ; j++) { | |
457 Node *inn = n->in(j); | |
458 if (inn) { | |
459 if (inn->is_Mach() && must_clone[inn->as_Mach()->ideal_Opcode()] ) { | |
460 n_choice = 3; | |
461 break; | |
462 } | |
463 } | |
464 } | |
465 | |
466 // MachTemps should be scheduled last so they are near their uses | |
467 if (n->is_MachTemp()) { | |
468 n_choice = 1; | |
469 } | |
470 | |
1685 | 471 uint n_latency = cfg->_node_latency->at_grow(n->_idx); |
0 | 472 uint n_score = n->req(); // Many inputs get high score to break ties |
473 | |
474 // Keep best latency found | |
475 if( choice < n_choice || | |
476 ( choice == n_choice && | |
477 ( latency < n_latency || | |
478 ( latency == n_latency && | |
479 ( score < n_score ))))) { | |
480 choice = n_choice; | |
481 latency = n_latency; | |
482 score = n_score; | |
483 idx = i; // Also keep index in worklist | |
484 } | |
485 } // End of for all ready nodes in worklist | |
486 | |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
487 assert(idx >= 0, "index should be set"); |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
488 Node *n = worklist[(uint)idx]; // Get the winner |
0 | 489 |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
490 worklist.map((uint)idx, worklist.pop()); // Compress worklist |
0 | 491 return n; |
492 } | |
493 | |
494 | |
495 //------------------------------set_next_call---------------------------------- | |
496 void Block::set_next_call( Node *n, VectorSet &next_call, Block_Array &bbs ) { | |
497 if( next_call.test_set(n->_idx) ) return; | |
498 for( uint i=0; i<n->len(); i++ ) { | |
499 Node *m = n->in(i); | |
500 if( !m ) continue; // must see all nodes in block that precede call | |
501 if( bbs[m->_idx] == this ) | |
502 set_next_call( m, next_call, bbs ); | |
503 } | |
504 } | |
505 | |
506 //------------------------------needed_for_next_call--------------------------- | |
507 // Set the flag 'next_call' for each Node that is needed for the next call to | |
508 // be scheduled. This flag lets me bias scheduling so Nodes needed for the | |
509 // next subroutine call get priority - basically it moves things NOT needed | |
510 // for the next call till after the call. This prevents me from trying to | |
511 // carry lots of stuff live across a call. | |
512 void Block::needed_for_next_call(Node *this_call, VectorSet &next_call, Block_Array &bbs) { | |
513 // Find the next control-defining Node in this block | |
514 Node* call = NULL; | |
515 for (DUIterator_Fast imax, i = this_call->fast_outs(imax); i < imax; i++) { | |
516 Node* m = this_call->fast_out(i); | |
517 if( bbs[m->_idx] == this && // Local-block user | |
518 m != this_call && // Not self-start node | |
519 m->is_Call() ) | |
520 call = m; | |
521 break; | |
522 } | |
523 if (call == NULL) return; // No next call (e.g., block end is near) | |
524 // Set next-call for all inputs to this call | |
525 set_next_call(call, next_call, bbs); | |
526 } | |
527 | |
528 //------------------------------sched_call------------------------------------- | |
529 uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, int *ready_cnt, MachCallNode *mcall, VectorSet &next_call ) { | |
530 RegMask regs; | |
531 | |
532 // Schedule all the users of the call right now. All the users are | |
533 // projection Nodes, so they must be scheduled next to the call. | |
534 // Collect all the defined registers. | |
535 for (DUIterator_Fast imax, i = mcall->fast_outs(imax); i < imax; i++) { | |
536 Node* n = mcall->fast_out(i); | |
537 assert( n->Opcode()==Op_MachProj, "" ); | |
538 --ready_cnt[n->_idx]; | |
539 assert( !ready_cnt[n->_idx], "" ); | |
540 // Schedule next to call | |
541 _nodes.map(node_cnt++, n); | |
542 // Collect defined registers | |
543 regs.OR(n->out_RegMask()); | |
544 // Check for scheduling the next control-definer | |
545 if( n->bottom_type() == Type::CONTROL ) | |
546 // Warm up next pile of heuristic bits | |
547 needed_for_next_call(n, next_call, bbs); | |
548 | |
549 // Children of projections are now all ready | |
550 for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | |
551 Node* m = n->fast_out(j); // Get user | |
552 if( bbs[m->_idx] != this ) continue; | |
553 if( m->is_Phi() ) continue; | |
554 if( !--ready_cnt[m->_idx] ) | |
555 worklist.push(m); | |
556 } | |
557 | |
558 } | |
559 | |
560 // Act as if the call defines the Frame Pointer. | |
561 // Certainly the FP is alive and well after the call. | |
562 regs.Insert(matcher.c_frame_pointer()); | |
563 | |
564 // Set all registers killed and not already defined by the call. | |
565 uint r_cnt = mcall->tf()->range()->cnt(); | |
566 int op = mcall->ideal_Opcode(); | |
567 MachProjNode *proj = new (matcher.C, 1) MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj ); | |
568 bbs.map(proj->_idx,this); | |
569 _nodes.insert(node_cnt++, proj); | |
570 | |
571 // Select the right register save policy. | |
572 const char * save_policy; | |
573 switch (op) { | |
574 case Op_CallRuntime: | |
575 case Op_CallLeaf: | |
576 case Op_CallLeafNoFP: | |
577 // Calling C code so use C calling convention | |
578 save_policy = matcher._c_reg_save_policy; | |
579 break; | |
580 | |
581 case Op_CallStaticJava: | |
582 case Op_CallDynamicJava: | |
583 // Calling Java code so use Java calling convention | |
584 save_policy = matcher._register_save_policy; | |
585 break; | |
586 | |
587 default: | |
588 ShouldNotReachHere(); | |
589 } | |
590 | |
591 // When using CallRuntime mark SOE registers as killed by the call | |
592 // so values that could show up in the RegisterMap aren't live in a | |
593 // callee saved register since the register wouldn't know where to | |
594 // find them. CallLeaf and CallLeafNoFP are ok because they can't | |
595 // have debug info on them. Strictly speaking this only needs to be | |
596 // done for oops since idealreg2debugmask takes care of debug info | |
597 // references but there no way to handle oops differently than other | |
598 // pointers as far as the kill mask goes. | |
599 bool exclude_soe = op == Op_CallRuntime; | |
600 | |
1137
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
601 // If the call is a MethodHandle invoke, we need to exclude the |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
602 // register which is used to save the SP value over MH invokes from |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
603 // the mask. Otherwise this register could be used for |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
604 // deoptimization information. |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
605 if (op == Op_CallStaticJava) { |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
606 MachCallStaticJavaNode* mcallstaticjava = (MachCallStaticJavaNode*) mcall; |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
607 if (mcallstaticjava->_method_handle_invoke) |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
608 proj->_rout.OR(Matcher::method_handle_invoke_SP_save_mask()); |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
609 } |
97125851f396
6829187: compiler optimizations required for JSR 292
twisti
parents:
1100
diff
changeset
|
610 |
0 | 611 // Fill in the kill mask for the call |
612 for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) { | |
613 if( !regs.Member(r) ) { // Not already defined by the call | |
614 // Save-on-call register? | |
615 if ((save_policy[r] == 'C') || | |
616 (save_policy[r] == 'A') || | |
617 ((save_policy[r] == 'E') && exclude_soe)) { | |
618 proj->_rout.Insert(r); | |
619 } | |
620 } | |
621 } | |
622 | |
623 return node_cnt; | |
624 } | |
625 | |
626 | |
627 //------------------------------schedule_local--------------------------------- | |
628 // Topological sort within a block. Someday become a real scheduler. | |
629 bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, VectorSet &next_call) { | |
630 // Already "sorted" are the block start Node (as the first entry), and | |
631 // the block-ending Node and any trailing control projections. We leave | |
632 // these alone. PhiNodes and ParmNodes are made to follow the block start | |
633 // Node. Everything else gets topo-sorted. | |
634 | |
635 #ifndef PRODUCT | |
636 if (cfg->trace_opto_pipelining()) { | |
637 tty->print_cr("# --- schedule_local B%d, before: ---", _pre_order); | |
638 for (uint i = 0;i < _nodes.size();i++) { | |
639 tty->print("# "); | |
640 _nodes[i]->fast_dump(); | |
641 } | |
642 tty->print_cr("#"); | |
643 } | |
644 #endif | |
645 | |
646 // RootNode is already sorted | |
647 if( _nodes.size() == 1 ) return true; | |
648 | |
649 // Move PhiNodes and ParmNodes from 1 to cnt up to the start | |
650 uint node_cnt = end_idx(); | |
651 uint phi_cnt = 1; | |
652 uint i; | |
653 for( i = 1; i<node_cnt; i++ ) { // Scan for Phi | |
654 Node *n = _nodes[i]; | |
655 if( n->is_Phi() || // Found a PhiNode or ParmNode | |
656 (n->is_Proj() && n->in(0) == head()) ) { | |
657 // Move guy at 'phi_cnt' to the end; makes a hole at phi_cnt | |
658 _nodes.map(i,_nodes[phi_cnt]); | |
659 _nodes.map(phi_cnt++,n); // swap Phi/Parm up front | |
660 } else { // All others | |
661 // Count block-local inputs to 'n' | |
662 uint cnt = n->len(); // Input count | |
663 uint local = 0; | |
664 for( uint j=0; j<cnt; j++ ) { | |
665 Node *m = n->in(j); | |
666 if( m && cfg->_bbs[m->_idx] == this && !m->is_top() ) | |
667 local++; // One more block-local input | |
668 } | |
669 ready_cnt[n->_idx] = local; // Count em up | |
670 | |
671 // A few node types require changing a required edge to a precedence edge | |
672 // before allocation. | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
125
diff
changeset
|
673 if( UseConcMarkSweepGC || UseG1GC ) { |
0 | 674 if( n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_StoreCM ) { |
675 // Note: Required edges with an index greater than oper_input_base | |
676 // are not supported by the allocator. | |
677 // Note2: Can only depend on unmatched edge being last, | |
678 // can not depend on its absolute position. | |
679 Node *oop_store = n->in(n->req() - 1); | |
680 n->del_req(n->req() - 1); | |
681 n->add_prec(oop_store); | |
682 assert(cfg->_bbs[oop_store->_idx]->_dom_depth <= this->_dom_depth, "oop_store must dominate card-mark"); | |
683 } | |
684 } | |
1100
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
681
diff
changeset
|
685 if( n->is_Mach() && n->req() > TypeFunc::Parms && |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
681
diff
changeset
|
686 (n->as_Mach()->ideal_Opcode() == Op_MemBarAcquire || |
f96a1a986f7b
6895383: JCK test throws NPE for method compiled with Escape Analysis
kvn
parents:
681
diff
changeset
|
687 n->as_Mach()->ideal_Opcode() == Op_MemBarVolatile) ) { |
253
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
688 // MemBarAcquire could be created without Precedent edge. |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
689 // del_req() replaces the specified edge with the last input edge |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
690 // and then removes the last edge. If the specified edge > number of |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
691 // edges the last edge will be moved outside of the input edges array |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
692 // and the edge will be lost. This is why this code should be |
b0fe4deeb9fb
6726999: nsk/stress/jck12a/jck12a010 assert(n != null,"Bad immediate dominator info.")
kvn
parents:
196
diff
changeset
|
693 // executed only when Precedent (== TypeFunc::Parms) edge is present. |
0 | 694 Node *x = n->in(TypeFunc::Parms); |
695 n->del_req(TypeFunc::Parms); | |
696 n->add_prec(x); | |
697 } | |
698 } | |
699 } | |
700 for(uint i2=i; i2<_nodes.size(); i2++ ) // Trailing guys get zapped count | |
701 ready_cnt[_nodes[i2]->_idx] = 0; | |
702 | |
703 // All the prescheduled guys do not hold back internal nodes | |
704 uint i3; | |
705 for(i3 = 0; i3<phi_cnt; i3++ ) { // For all pre-scheduled | |
706 Node *n = _nodes[i3]; // Get pre-scheduled | |
707 for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | |
708 Node* m = n->fast_out(j); | |
709 if( cfg->_bbs[m->_idx] ==this ) // Local-block user | |
710 ready_cnt[m->_idx]--; // Fix ready count | |
711 } | |
712 } | |
713 | |
714 Node_List delay; | |
715 // Make a worklist | |
716 Node_List worklist; | |
717 for(uint i4=i3; i4<node_cnt; i4++ ) { // Put ready guys on worklist | |
718 Node *m = _nodes[i4]; | |
719 if( !ready_cnt[m->_idx] ) { // Zero ready count? | |
720 if (m->is_iteratively_computed()) { | |
721 // Push induction variable increments last to allow other uses | |
722 // of the phi to be scheduled first. The select() method breaks | |
723 // ties in scheduling by worklist order. | |
724 delay.push(m); | |
125
d942c7e64bd9
6601321: Assert(j == 1 || b->_nodes[j-1]->is_Phi(),"CreateEx must be first instruction in block")
never
parents:
113
diff
changeset
|
725 } else if (m->is_Mach() && m->as_Mach()->ideal_Opcode() == Op_CreateEx) { |
d942c7e64bd9
6601321: Assert(j == 1 || b->_nodes[j-1]->is_Phi(),"CreateEx must be first instruction in block")
never
parents:
113
diff
changeset
|
726 // Force the CreateEx to the top of the list so it's processed |
d942c7e64bd9
6601321: Assert(j == 1 || b->_nodes[j-1]->is_Phi(),"CreateEx must be first instruction in block")
never
parents:
113
diff
changeset
|
727 // first and ends up at the start of the block. |
d942c7e64bd9
6601321: Assert(j == 1 || b->_nodes[j-1]->is_Phi(),"CreateEx must be first instruction in block")
never
parents:
113
diff
changeset
|
728 worklist.insert(0, m); |
0 | 729 } else { |
730 worklist.push(m); // Then on to worklist! | |
731 } | |
732 } | |
733 } | |
734 while (delay.size()) { | |
735 Node* d = delay.pop(); | |
736 worklist.push(d); | |
737 } | |
738 | |
739 // Warm up the 'next_call' heuristic bits | |
740 needed_for_next_call(_nodes[0], next_call, cfg->_bbs); | |
741 | |
742 #ifndef PRODUCT | |
743 if (cfg->trace_opto_pipelining()) { | |
744 for (uint j=0; j<_nodes.size(); j++) { | |
745 Node *n = _nodes[j]; | |
746 int idx = n->_idx; | |
747 tty->print("# ready cnt:%3d ", ready_cnt[idx]); | |
1685 | 748 tty->print("latency:%3d ", cfg->_node_latency->at_grow(idx)); |
0 | 749 tty->print("%4d: %s\n", idx, n->Name()); |
750 } | |
751 } | |
752 #endif | |
753 | |
754 // Pull from worklist and schedule | |
755 while( worklist.size() ) { // Worklist is not ready | |
756 | |
757 #ifndef PRODUCT | |
758 if (cfg->trace_opto_pipelining()) { | |
759 tty->print("# ready list:"); | |
760 for( uint i=0; i<worklist.size(); i++ ) { // Inspect entire worklist | |
761 Node *n = worklist[i]; // Get Node on worklist | |
762 tty->print(" %d", n->_idx); | |
763 } | |
764 tty->cr(); | |
765 } | |
766 #endif | |
767 | |
768 // Select and pop a ready guy from worklist | |
769 Node* n = select(cfg, worklist, ready_cnt, next_call, phi_cnt); | |
770 _nodes.map(phi_cnt++,n); // Schedule him next | |
771 | |
772 #ifndef PRODUCT | |
773 if (cfg->trace_opto_pipelining()) { | |
774 tty->print("# select %d: %s", n->_idx, n->Name()); | |
1685 | 775 tty->print(", latency:%d", cfg->_node_latency->at_grow(n->_idx)); |
0 | 776 n->dump(); |
777 if (Verbose) { | |
778 tty->print("# ready list:"); | |
779 for( uint i=0; i<worklist.size(); i++ ) { // Inspect entire worklist | |
780 Node *n = worklist[i]; // Get Node on worklist | |
781 tty->print(" %d", n->_idx); | |
782 } | |
783 tty->cr(); | |
784 } | |
785 } | |
786 | |
787 #endif | |
788 if( n->is_MachCall() ) { | |
789 MachCallNode *mcall = n->as_MachCall(); | |
790 phi_cnt = sched_call(matcher, cfg->_bbs, phi_cnt, worklist, ready_cnt, mcall, next_call); | |
791 continue; | |
792 } | |
793 // Children are now all ready | |
794 for (DUIterator_Fast i5max, i5 = n->fast_outs(i5max); i5 < i5max; i5++) { | |
795 Node* m = n->fast_out(i5); // Get user | |
796 if( cfg->_bbs[m->_idx] != this ) continue; | |
797 if( m->is_Phi() ) continue; | |
798 if( !--ready_cnt[m->_idx] ) | |
799 worklist.push(m); | |
800 } | |
801 } | |
802 | |
803 if( phi_cnt != end_idx() ) { | |
804 // did not schedule all. Retry, Bailout, or Die | |
805 Compile* C = matcher.C; | |
806 if (C->subsume_loads() == true && !C->failing()) { | |
807 // Retry with subsume_loads == false | |
808 // If this is the first failure, the sentinel string will "stick" | |
809 // to the Compile object, and the C2Compiler will see it and retry. | |
810 C->record_failure(C2Compiler::retry_no_subsuming_loads()); | |
811 } | |
812 // assert( phi_cnt == end_idx(), "did not schedule all" ); | |
813 return false; | |
814 } | |
815 | |
816 #ifndef PRODUCT | |
817 if (cfg->trace_opto_pipelining()) { | |
818 tty->print_cr("#"); | |
819 tty->print_cr("# after schedule_local"); | |
820 for (uint i = 0;i < _nodes.size();i++) { | |
821 tty->print("# "); | |
822 _nodes[i]->fast_dump(); | |
823 } | |
824 tty->cr(); | |
825 } | |
826 #endif | |
827 | |
828 | |
829 return true; | |
830 } | |
831 | |
832 //--------------------------catch_cleanup_fix_all_inputs----------------------- | |
833 static void catch_cleanup_fix_all_inputs(Node *use, Node *old_def, Node *new_def) { | |
834 for (uint l = 0; l < use->len(); l++) { | |
835 if (use->in(l) == old_def) { | |
836 if (l < use->req()) { | |
837 use->set_req(l, new_def); | |
838 } else { | |
839 use->rm_prec(l); | |
840 use->add_prec(new_def); | |
841 l--; | |
842 } | |
843 } | |
844 } | |
845 } | |
846 | |
847 //------------------------------catch_cleanup_find_cloned_def------------------ | |
848 static Node *catch_cleanup_find_cloned_def(Block *use_blk, Node *def, Block *def_blk, Block_Array &bbs, int n_clone_idx) { | |
849 assert( use_blk != def_blk, "Inter-block cleanup only"); | |
850 | |
851 // The use is some block below the Catch. Find and return the clone of the def | |
852 // that dominates the use. If there is no clone in a dominating block, then | |
853 // create a phi for the def in a dominating block. | |
854 | |
855 // Find which successor block dominates this use. The successor | |
856 // blocks must all be single-entry (from the Catch only; I will have | |
857 // split blocks to make this so), hence they all dominate. | |
858 while( use_blk->_dom_depth > def_blk->_dom_depth+1 ) | |
859 use_blk = use_blk->_idom; | |
860 | |
861 // Find the successor | |
862 Node *fixup = NULL; | |
863 | |
864 uint j; | |
865 for( j = 0; j < def_blk->_num_succs; j++ ) | |
866 if( use_blk == def_blk->_succs[j] ) | |
867 break; | |
868 | |
869 if( j == def_blk->_num_succs ) { | |
870 // Block at same level in dom-tree is not a successor. It needs a | |
871 // PhiNode, the PhiNode uses from the def and IT's uses need fixup. | |
872 Node_Array inputs = new Node_List(Thread::current()->resource_area()); | |
873 for(uint k = 1; k < use_blk->num_preds(); k++) { | |
874 inputs.map(k, catch_cleanup_find_cloned_def(bbs[use_blk->pred(k)->_idx], def, def_blk, bbs, n_clone_idx)); | |
875 } | |
876 | |
877 // Check to see if the use_blk already has an identical phi inserted. | |
878 // If it exists, it will be at the first position since all uses of a | |
879 // def are processed together. | |
880 Node *phi = use_blk->_nodes[1]; | |
881 if( phi->is_Phi() ) { | |
882 fixup = phi; | |
883 for (uint k = 1; k < use_blk->num_preds(); k++) { | |
884 if (phi->in(k) != inputs[k]) { | |
885 // Not a match | |
886 fixup = NULL; | |
887 break; | |
888 } | |
889 } | |
890 } | |
891 | |
892 // If an existing PhiNode was not found, make a new one. | |
893 if (fixup == NULL) { | |
894 Node *new_phi = PhiNode::make(use_blk->head(), def); | |
895 use_blk->_nodes.insert(1, new_phi); | |
896 bbs.map(new_phi->_idx, use_blk); | |
897 for (uint k = 1; k < use_blk->num_preds(); k++) { | |
898 new_phi->set_req(k, inputs[k]); | |
899 } | |
900 fixup = new_phi; | |
901 } | |
902 | |
903 } else { | |
904 // Found the use just below the Catch. Make it use the clone. | |
905 fixup = use_blk->_nodes[n_clone_idx]; | |
906 } | |
907 | |
908 return fixup; | |
909 } | |
910 | |
911 //--------------------------catch_cleanup_intra_block-------------------------- | |
912 // Fix all input edges in use that reference "def". The use is in the same | |
913 // block as the def and both have been cloned in each successor block. | |
914 static void catch_cleanup_intra_block(Node *use, Node *def, Block *blk, int beg, int n_clone_idx) { | |
915 | |
916 // Both the use and def have been cloned. For each successor block, | |
917 // get the clone of the use, and make its input the clone of the def | |
918 // found in that block. | |
919 | |
920 uint use_idx = blk->find_node(use); | |
921 uint offset_idx = use_idx - beg; | |
922 for( uint k = 0; k < blk->_num_succs; k++ ) { | |
923 // Get clone in each successor block | |
924 Block *sb = blk->_succs[k]; | |
925 Node *clone = sb->_nodes[offset_idx+1]; | |
926 assert( clone->Opcode() == use->Opcode(), "" ); | |
927 | |
928 // Make use-clone reference the def-clone | |
929 catch_cleanup_fix_all_inputs(clone, def, sb->_nodes[n_clone_idx]); | |
930 } | |
931 } | |
932 | |
933 //------------------------------catch_cleanup_inter_block--------------------- | |
934 // Fix all input edges in use that reference "def". The use is in a different | |
935 // block than the def. | |
936 static void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Block *def_blk, Block_Array &bbs, int n_clone_idx) { | |
937 if( !use_blk ) return; // Can happen if the use is a precedence edge | |
938 | |
939 Node *new_def = catch_cleanup_find_cloned_def(use_blk, def, def_blk, bbs, n_clone_idx); | |
940 catch_cleanup_fix_all_inputs(use, def, new_def); | |
941 } | |
942 | |
943 //------------------------------call_catch_cleanup----------------------------- | |
944 // If we inserted any instructions between a Call and his CatchNode, | |
945 // clone the instructions on all paths below the Catch. | |
946 void Block::call_catch_cleanup(Block_Array &bbs) { | |
947 | |
948 // End of region to clone | |
949 uint end = end_idx(); | |
950 if( !_nodes[end]->is_Catch() ) return; | |
951 // Start of region to clone | |
952 uint beg = end; | |
953 while( _nodes[beg-1]->Opcode() != Op_MachProj || | |
954 !_nodes[beg-1]->in(0)->is_Call() ) { | |
955 beg--; | |
956 assert(beg > 0,"Catch cleanup walking beyond block boundary"); | |
957 } | |
958 // Range of inserted instructions is [beg, end) | |
959 if( beg == end ) return; | |
960 | |
961 // Clone along all Catch output paths. Clone area between the 'beg' and | |
962 // 'end' indices. | |
963 for( uint i = 0; i < _num_succs; i++ ) { | |
964 Block *sb = _succs[i]; | |
965 // Clone the entire area; ignoring the edge fixup for now. | |
966 for( uint j = end; j > beg; j-- ) { | |
1693
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
967 // It is safe here to clone a node with anti_dependence |
6c9cc03d8726
6973329: C2 with Zero based COOP produces code with broken anti-dependency on x86
kvn
parents:
1685
diff
changeset
|
968 // since clones dominate on each path. |
0 | 969 Node *clone = _nodes[j-1]->clone(); |
970 sb->_nodes.insert( 1, clone ); | |
971 bbs.map(clone->_idx,sb); | |
972 } | |
973 } | |
974 | |
975 | |
976 // Fixup edges. Check the def-use info per cloned Node | |
977 for(uint i2 = beg; i2 < end; i2++ ) { | |
978 uint n_clone_idx = i2-beg+1; // Index of clone of n in each successor block | |
979 Node *n = _nodes[i2]; // Node that got cloned | |
980 // Need DU safe iterator because of edge manipulation in calls. | |
981 Unique_Node_List *out = new Unique_Node_List(Thread::current()->resource_area()); | |
982 for (DUIterator_Fast j1max, j1 = n->fast_outs(j1max); j1 < j1max; j1++) { | |
983 out->push(n->fast_out(j1)); | |
984 } | |
985 uint max = out->size(); | |
986 for (uint j = 0; j < max; j++) {// For all users | |
987 Node *use = out->pop(); | |
988 Block *buse = bbs[use->_idx]; | |
989 if( use->is_Phi() ) { | |
990 for( uint k = 1; k < use->req(); k++ ) | |
991 if( use->in(k) == n ) { | |
992 Node *fixup = catch_cleanup_find_cloned_def(bbs[buse->pred(k)->_idx], n, this, bbs, n_clone_idx); | |
993 use->set_req(k, fixup); | |
994 } | |
995 } else { | |
996 if (this == buse) { | |
997 catch_cleanup_intra_block(use, n, this, beg, n_clone_idx); | |
998 } else { | |
999 catch_cleanup_inter_block(use, buse, n, this, bbs, n_clone_idx); | |
1000 } | |
1001 } | |
1002 } // End for all users | |
1003 | |
1004 } // End of for all Nodes in cloned area | |
1005 | |
1006 // Remove the now-dead cloned ops | |
1007 for(uint i3 = beg; i3 < end; i3++ ) { | |
1008 _nodes[beg]->disconnect_inputs(NULL); | |
1009 _nodes.remove(beg); | |
1010 } | |
1011 | |
1012 // If the successor blocks have a CreateEx node, move it back to the top | |
1013 for(uint i4 = 0; i4 < _num_succs; i4++ ) { | |
1014 Block *sb = _succs[i4]; | |
1015 uint new_cnt = end - beg; | |
1016 // Remove any newly created, but dead, nodes. | |
1017 for( uint j = new_cnt; j > 0; j-- ) { | |
1018 Node *n = sb->_nodes[j]; | |
1019 if (n->outcnt() == 0 && | |
1020 (!n->is_Proj() || n->as_Proj()->in(0)->outcnt() == 1) ){ | |
1021 n->disconnect_inputs(NULL); | |
1022 sb->_nodes.remove(j); | |
1023 new_cnt--; | |
1024 } | |
1025 } | |
1026 // If any newly created nodes remain, move the CreateEx node to the top | |
1027 if (new_cnt > 0) { | |
1028 Node *cex = sb->_nodes[1+new_cnt]; | |
1029 if( cex->is_Mach() && cex->as_Mach()->ideal_Opcode() == Op_CreateEx ) { | |
1030 sb->_nodes.remove(1+new_cnt); | |
1031 sb->_nodes.insert(1,cex); | |
1032 } | |
1033 } | |
1034 } | |
1035 } |