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