File: | jdk/src/hotspot/share/opto/loopnode.hpp |
Warning: | line 933, column 5 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | |||
2 | * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. | |||
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 | * | |||
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |||
20 | * or visit www.oracle.com if you need additional information or have any | |||
21 | * questions. | |||
22 | * | |||
23 | */ | |||
24 | ||||
25 | #include "precompiled.hpp" | |||
26 | #include "memory/allocation.inline.hpp" | |||
27 | #include "opto/callnode.hpp" | |||
28 | #include "opto/loopnode.hpp" | |||
29 | #include "opto/movenode.hpp" | |||
30 | ||||
31 | ||||
32 | //------------------------------split_thru_region------------------------------ | |||
33 | // Split Node 'n' through merge point. | |||
34 | Node *PhaseIdealLoop::split_thru_region( Node *n, Node *region ) { | |||
35 | uint wins = 0; | |||
36 | assert( n->is_CFG(), "" )do { if (!(n->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 36, "assert(" "n->is_CFG()" ") failed", ""); ::breakpoint (); } } while (0); | |||
37 | assert( region->is_Region(), "" )do { if (!(region->is_Region())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 37, "assert(" "region->is_Region()" ") failed", ""); ::breakpoint (); } } while (0); | |||
38 | Node *r = new RegionNode( region->req() ); | |||
39 | IdealLoopTree *loop = get_loop( n ); | |||
40 | for( uint i = 1; i < region->req(); i++ ) { | |||
41 | Node *x = n->clone(); | |||
42 | Node *in0 = n->in(0); | |||
43 | if( in0->in(0) == region ) x->set_req( 0, in0->in(i) ); | |||
44 | for( uint j = 1; j < n->req(); j++ ) { | |||
45 | Node *in = n->in(j); | |||
46 | if( get_ctrl(in) == region ) | |||
47 | x->set_req( j, in->in(i) ); | |||
48 | } | |||
49 | _igvn.register_new_node_with_optimizer(x); | |||
50 | set_loop(x, loop); | |||
51 | set_idom(x, x->in(0), dom_depth(x->in(0))+1); | |||
52 | r->init_req(i, x); | |||
53 | } | |||
54 | ||||
55 | // Record region | |||
56 | r->set_req(0,region); // Not a TRUE RegionNode | |||
57 | _igvn.register_new_node_with_optimizer(r); | |||
58 | set_loop(r, loop); | |||
59 | if( !loop->_child ) | |||
60 | loop->_body.push(r); | |||
61 | return r; | |||
62 | } | |||
63 | ||||
64 | //------------------------------split_up--------------------------------------- | |||
65 | // Split block-local op up through the phis to empty the current block | |||
66 | bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { | |||
67 | if( n->is_CFG() ) { | |||
| ||||
68 | assert( n->in(0) != blk1, "Lousy candidate for split-if" )do { if (!(n->in(0) != blk1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 68, "assert(" "n->in(0) != blk1" ") failed", "Lousy candidate for split-if" ); ::breakpoint(); } } while (0); | |||
69 | return false; | |||
70 | } | |||
71 | if( get_ctrl(n) != blk1 && get_ctrl(n) != blk2 ) | |||
72 | return false; // Not block local | |||
73 | if( n->is_Phi() ) return false; // Local PHIs are expected | |||
74 | ||||
75 | // Recursively split-up inputs | |||
76 | for (uint i = 1; i < n->req(); i++) { | |||
77 | if( split_up( n->in(i), blk1, blk2 ) ) { | |||
78 | // Got split recursively and self went dead? | |||
79 | if (n->outcnt() == 0) | |||
80 | _igvn.remove_dead_node(n); | |||
81 | return true; | |||
82 | } | |||
83 | } | |||
84 | ||||
85 | // Check for needing to clone-up a compare. Can't do that, it forces | |||
86 | // another (nested) split-if transform. Instead, clone it "down". | |||
87 | if( n->is_Cmp() ) { | |||
88 | assert(get_ctrl(n) == blk2 || get_ctrl(n) == blk1, "must be in block with IF")do { if (!(get_ctrl(n) == blk2 || get_ctrl(n) == blk1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 88, "assert(" "get_ctrl(n) == blk2 || get_ctrl(n) == blk1" ") failed" , "must be in block with IF"); ::breakpoint(); } } while (0); | |||
89 | // Check for simple Cmp/Bool/CMove which we can clone-up. Cmp/Bool/CMove | |||
90 | // sequence can have no other users and it must all reside in the split-if | |||
91 | // block. Non-simple Cmp/Bool/CMove sequences are 'cloned-down' below - | |||
92 | // private, per-use versions of the Cmp and Bool are made. These sink to | |||
93 | // the CMove block. If the CMove is in the split-if block, then in the | |||
94 | // next iteration this will become a simple Cmp/Bool/CMove set to clone-up. | |||
95 | Node *bol, *cmov; | |||
96 | if( !(n->outcnt() == 1 && n->unique_out()->is_Bool() && | |||
97 | (bol = n->unique_out()->as_Bool()) && | |||
98 | (get_ctrl(bol) == blk1 || | |||
99 | get_ctrl(bol) == blk2) && | |||
100 | bol->outcnt() == 1 && | |||
101 | bol->unique_out()->is_CMove() && | |||
102 | (cmov = bol->unique_out()->as_CMove()) && | |||
103 | (get_ctrl(cmov) == blk1 || | |||
104 | get_ctrl(cmov) == blk2) ) ) { | |||
105 | ||||
106 | // Must clone down | |||
107 | #ifndef PRODUCT | |||
108 | if( PrintOpto && VerifyLoopOptimizations ) { | |||
109 | tty->print("Cloning down: "); | |||
110 | n->dump(); | |||
111 | } | |||
112 | #endif | |||
113 | if (!n->is_FastLock()) { | |||
114 | // Clone down any block-local BoolNode uses of this CmpNode | |||
115 | for (DUIterator i = n->outs(); n->has_out(i); i++) { | |||
116 | Node* bol = n->out(i); | |||
117 | assert( bol->is_Bool(), "" )do { if (!(bol->is_Bool())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 117, "assert(" "bol->is_Bool()" ") failed", ""); ::breakpoint (); } } while (0); | |||
118 | if (bol->outcnt() == 1) { | |||
119 | Node* use = bol->unique_out(); | |||
120 | if (use->Opcode() == Op_Opaque4) { | |||
121 | if (use->outcnt() == 1) { | |||
122 | Node* iff = use->unique_out(); | |||
123 | assert(iff->is_If(), "unexpected node type")do { if (!(iff->is_If())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 123, "assert(" "iff->is_If()" ") failed", "unexpected node type" ); ::breakpoint(); } } while (0); | |||
124 | Node *use_c = iff->in(0); | |||
125 | if (use_c == blk1 || use_c == blk2) { | |||
126 | continue; | |||
127 | } | |||
128 | } | |||
129 | } else { | |||
130 | // We might see an Opaque1 from a loop limit check here | |||
131 | assert(use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1, "unexpected node type")do { if (!(use->is_If() || use->is_CMove() || use->Opcode () == Op_Opaque1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 131, "assert(" "use->is_If() || use->is_CMove() || use->Opcode() == Op_Opaque1" ") failed", "unexpected node type"); ::breakpoint(); } } while (0); | |||
132 | Node *use_c = use->is_If() ? use->in(0) : get_ctrl(use); | |||
133 | if (use_c == blk1 || use_c == blk2) { | |||
134 | assert(use->is_CMove(), "unexpected node type")do { if (!(use->is_CMove())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 134, "assert(" "use->is_CMove()" ") failed", "unexpected node type" ); ::breakpoint(); } } while (0); | |||
135 | continue; | |||
136 | } | |||
137 | } | |||
138 | } | |||
139 | if (get_ctrl(bol) == blk1 || get_ctrl(bol) == blk2) { | |||
140 | // Recursively sink any BoolNode | |||
141 | #ifndef PRODUCT | |||
142 | if( PrintOpto && VerifyLoopOptimizations ) { | |||
143 | tty->print("Cloning down: "); | |||
144 | bol->dump(); | |||
145 | } | |||
146 | #endif | |||
147 | for (DUIterator j = bol->outs(); bol->has_out(j); j++) { | |||
148 | Node* u = bol->out(j); | |||
149 | // Uses are either IfNodes, CMoves or Opaque4 | |||
150 | if (u->Opcode() == Op_Opaque4) { | |||
151 | assert(u->in(1) == bol, "bad input")do { if (!(u->in(1) == bol)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 151, "assert(" "u->in(1) == bol" ") failed", "bad input" ); ::breakpoint(); } } while (0); | |||
152 | for (DUIterator_Last kmin, k = u->last_outs(kmin); k >= kmin; --k) { | |||
153 | Node* iff = u->last_out(k); | |||
154 | assert(iff->is_If() || iff->is_CMove(), "unexpected node type")do { if (!(iff->is_If() || iff->is_CMove())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 154, "assert(" "iff->is_If() || iff->is_CMove()" ") failed" , "unexpected node type"); ::breakpoint(); } } while (0); | |||
155 | assert( iff->in(1) == u, "" )do { if (!(iff->in(1) == u)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 155, "assert(" "iff->in(1) == u" ") failed", ""); ::breakpoint (); } } while (0); | |||
156 | // Get control block of either the CMove or the If input | |||
157 | Node *iff_ctrl = iff->is_If() ? iff->in(0) : get_ctrl(iff); | |||
158 | Node *x1 = bol->clone(); | |||
159 | Node *x2 = u->clone(); | |||
160 | register_new_node(x1, iff_ctrl); | |||
161 | register_new_node(x2, iff_ctrl); | |||
162 | _igvn.replace_input_of(x2, 1, x1); | |||
163 | _igvn.replace_input_of(iff, 1, x2); | |||
164 | } | |||
165 | _igvn.remove_dead_node(u); | |||
166 | --j; | |||
167 | } else { | |||
168 | // We might see an Opaque1 from a loop limit check here | |||
169 | assert(u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1, "unexpected node type")do { if (!(u->is_If() || u->is_CMove() || u->Opcode( ) == Op_Opaque1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 169, "assert(" "u->is_If() || u->is_CMove() || u->Opcode() == Op_Opaque1" ") failed", "unexpected node type"); ::breakpoint(); } } while (0); | |||
170 | assert(u->in(1) == bol, "")do { if (!(u->in(1) == bol)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 170, "assert(" "u->in(1) == bol" ") failed", ""); ::breakpoint (); } } while (0); | |||
171 | // Get control block of either the CMove or the If input | |||
172 | Node *u_ctrl = u->is_If() ? u->in(0) : get_ctrl(u); | |||
173 | assert((u_ctrl != blk1 && u_ctrl != blk2) || u->is_CMove(), "won't converge")do { if (!((u_ctrl != blk1 && u_ctrl != blk2) || u-> is_CMove())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 173, "assert(" "(u_ctrl != blk1 && u_ctrl != blk2) || u->is_CMove()" ") failed", "won't converge"); ::breakpoint(); } } while (0); | |||
174 | Node *x = bol->clone(); | |||
175 | register_new_node(x, u_ctrl); | |||
176 | _igvn.replace_input_of(u, 1, x); | |||
177 | --j; | |||
178 | } | |||
179 | } | |||
180 | _igvn.remove_dead_node(bol); | |||
181 | --i; | |||
182 | } | |||
183 | } | |||
184 | } | |||
185 | // Clone down this CmpNode | |||
186 | for (DUIterator_Last jmin, j = n->last_outs(jmin); j >= jmin; --j) { | |||
187 | Node* use = n->last_out(j); | |||
188 | uint pos = 1; | |||
189 | if (n->is_FastLock()) { | |||
190 | pos = TypeFunc::Parms + 2; | |||
191 | assert(use->is_Lock(), "FastLock only used by LockNode")do { if (!(use->is_Lock())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 191, "assert(" "use->is_Lock()" ") failed", "FastLock only used by LockNode" ); ::breakpoint(); } } while (0); | |||
192 | } | |||
193 | assert(use->in(pos) == n, "" )do { if (!(use->in(pos) == n)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 193, "assert(" "use->in(pos) == n" ") failed", ""); ::breakpoint (); } } while (0); | |||
194 | Node *x = n->clone(); | |||
195 | register_new_node(x, ctrl_or_self(use)); | |||
196 | _igvn.replace_input_of(use, pos, x); | |||
197 | } | |||
198 | _igvn.remove_dead_node( n ); | |||
199 | ||||
200 | return true; | |||
201 | } | |||
202 | } | |||
203 | ||||
204 | // See if splitting-up a Store. Any anti-dep loads must go up as | |||
205 | // well. An anti-dep load might be in the wrong block, because in | |||
206 | // this particular layout/schedule we ignored anti-deps and allow | |||
207 | // memory to be alive twice. This only works if we do the same | |||
208 | // operations on anti-dep loads as we do their killing stores. | |||
209 | if( n->is_Store() && n->in(MemNode::Memory)->in(0) == n->in(0) ) { | |||
210 | // Get store's memory slice | |||
211 | int alias_idx = C->get_alias_index(_igvn.type(n->in(MemNode::Address))->is_ptr()); | |||
212 | ||||
213 | // Get memory-phi anti-dep loads will be using | |||
214 | Node *memphi = n->in(MemNode::Memory); | |||
215 | assert( memphi->is_Phi(), "" )do { if (!(memphi->is_Phi())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 215, "assert(" "memphi->is_Phi()" ") failed", ""); ::breakpoint (); } } while (0); | |||
216 | // Hoist any anti-dep load to the splitting block; | |||
217 | // it will then "split-up". | |||
218 | for (DUIterator_Fast imax,i = memphi->fast_outs(imax); i < imax; i++) { | |||
219 | Node *load = memphi->fast_out(i); | |||
220 | if( load->is_Load() && alias_idx == C->get_alias_index(_igvn.type(load->in(MemNode::Address))->is_ptr()) ) | |||
221 | set_ctrl(load,blk1); | |||
222 | } | |||
223 | } | |||
224 | ||||
225 | // Found some other Node; must clone it up | |||
226 | #ifndef PRODUCT | |||
227 | if( PrintOpto && VerifyLoopOptimizations ) { | |||
228 | tty->print("Cloning up: "); | |||
229 | n->dump(); | |||
230 | } | |||
231 | #endif | |||
232 | ||||
233 | // ConvI2L may have type information on it which becomes invalid if | |||
234 | // it moves up in the graph so change any clones so widen the type | |||
235 | // to TypeLong::INT when pushing it up. | |||
236 | const Type* rtype = NULL__null; | |||
237 | if (n->Opcode() == Op_ConvI2L && n->bottom_type() != TypeLong::INT) { | |||
238 | rtype = TypeLong::INT; | |||
239 | } | |||
240 | ||||
241 | // Now actually split-up this guy. One copy per control path merging. | |||
242 | Node *phi = PhiNode::make_blank(blk1, n); | |||
243 | for( uint j = 1; j < blk1->req(); j++ ) { | |||
244 | Node *x = n->clone(); | |||
245 | // Widen the type of the ConvI2L when pushing up. | |||
246 | if (rtype != NULL__null) x->as_Type()->set_type(rtype); | |||
247 | if( n->in(0) && n->in(0) == blk1 ) | |||
248 | x->set_req( 0, blk1->in(j) ); | |||
249 | for( uint i = 1; i < n->req(); i++ ) { | |||
250 | Node *m = n->in(i); | |||
251 | if( get_ctrl(m) == blk1 ) { | |||
252 | assert( m->in(0) == blk1, "" )do { if (!(m->in(0) == blk1)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 252, "assert(" "m->in(0) == blk1" ") failed", ""); ::breakpoint (); } } while (0); | |||
253 | x->set_req( i, m->in(j) ); | |||
254 | } | |||
255 | } | |||
256 | register_new_node( x, blk1->in(j) ); | |||
257 | phi->init_req( j, x ); | |||
258 | } | |||
259 | // Announce phi to optimizer | |||
260 | register_new_node(phi, blk1); | |||
261 | ||||
262 | // Remove cloned-up value from optimizer; use phi instead | |||
263 | _igvn.replace_node( n, phi ); | |||
264 | ||||
265 | // (There used to be a self-recursive call to split_up() here, | |||
266 | // but it is not needed. All necessary forward walking is done | |||
267 | // by do_split_if() below.) | |||
268 | ||||
269 | return true; | |||
270 | } | |||
271 | ||||
272 | //------------------------------register_new_node------------------------------ | |||
273 | void PhaseIdealLoop::register_new_node( Node *n, Node *blk ) { | |||
274 | assert(!n->is_CFG(), "must be data node")do { if (!(!n->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 274, "assert(" "!n->is_CFG()" ") failed", "must be data node" ); ::breakpoint(); } } while (0); | |||
275 | _igvn.register_new_node_with_optimizer(n); | |||
276 | set_ctrl(n, blk); | |||
277 | IdealLoopTree *loop = get_loop(blk); | |||
278 | if( !loop->_child ) | |||
279 | loop->_body.push(n); | |||
280 | } | |||
281 | ||||
282 | //------------------------------small_cache------------------------------------ | |||
283 | struct small_cache : public Dict { | |||
284 | ||||
285 | small_cache() : Dict( cmpkey, hashptr ) {} | |||
286 | Node *probe( Node *use_blk ) { return (Node*)((*this)[use_blk]); } | |||
287 | void lru_insert( Node *use_blk, Node *new_def ) { Insert(use_blk,new_def); } | |||
288 | }; | |||
289 | ||||
290 | //------------------------------spinup----------------------------------------- | |||
291 | // "Spin up" the dominator tree, starting at the use site and stopping when we | |||
292 | // find the post-dominating point. | |||
293 | ||||
294 | // We must be at the merge point which post-dominates 'new_false' and | |||
295 | // 'new_true'. Figure out which edges into the RegionNode eventually lead up | |||
296 | // to false and which to true. Put in a PhiNode to merge values; plug in | |||
297 | // the appropriate false-arm or true-arm values. If some path leads to the | |||
298 | // original IF, then insert a Phi recursively. | |||
299 | Node *PhaseIdealLoop::spinup( Node *iff_dom, Node *new_false, Node *new_true, Node *use_blk, Node *def, small_cache *cache ) { | |||
300 | if (use_blk->is_top()) // Handle dead uses | |||
301 | return use_blk; | |||
302 | Node *prior_n = (Node*)((intptr_t)0xdeadbeef); | |||
303 | Node *n = use_blk; // Get path input | |||
304 | assert( use_blk != iff_dom, "" )do { if (!(use_blk != iff_dom)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 304, "assert(" "use_blk != iff_dom" ") failed", ""); ::breakpoint (); } } while (0); | |||
305 | // Here's the "spinup" the dominator tree loop. Do a cache-check | |||
306 | // along the way, in case we've come this way before. | |||
307 | while( n != iff_dom ) { // Found post-dominating point? | |||
308 | prior_n = n; | |||
309 | n = idom(n); // Search higher | |||
310 | Node *s = cache->probe( prior_n ); // Check cache | |||
311 | if( s ) return s; // Cache hit! | |||
312 | } | |||
313 | ||||
314 | Node *phi_post; | |||
315 | if( prior_n == new_false || prior_n == new_true ) { | |||
316 | phi_post = def->clone(); | |||
317 | phi_post->set_req(0, prior_n ); | |||
318 | register_new_node(phi_post, prior_n); | |||
319 | } else { | |||
320 | // This method handles both control uses (looking for Regions) or data | |||
321 | // uses (looking for Phis). If looking for a control use, then we need | |||
322 | // to insert a Region instead of a Phi; however Regions always exist | |||
323 | // previously (the hash_find_insert below would always hit) so we can | |||
324 | // return the existing Region. | |||
325 | if( def->is_CFG() ) { | |||
326 | phi_post = prior_n; // If looking for CFG, return prior | |||
327 | } else { | |||
328 | assert( def->is_Phi(), "" )do { if (!(def->is_Phi())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 328, "assert(" "def->is_Phi()" ") failed", ""); ::breakpoint (); } } while (0); | |||
329 | assert( prior_n->is_Region(), "must be a post-dominating merge point" )do { if (!(prior_n->is_Region())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 329, "assert(" "prior_n->is_Region()" ") failed", "must be a post-dominating merge point" ); ::breakpoint(); } } while (0); | |||
330 | ||||
331 | // Need a Phi here | |||
332 | phi_post = PhiNode::make_blank(prior_n, def); | |||
333 | // Search for both true and false on all paths till find one. | |||
334 | for( uint i = 1; i < phi_post->req(); i++ ) // For all paths | |||
335 | phi_post->init_req( i, spinup( iff_dom, new_false, new_true, prior_n->in(i), def, cache ) ); | |||
336 | Node *t = _igvn.hash_find_insert(phi_post); | |||
337 | if( t ) { // See if we already have this one | |||
338 | // phi_post will not be used, so kill it | |||
339 | _igvn.remove_dead_node(phi_post); | |||
340 | phi_post->destruct(&_igvn); | |||
341 | phi_post = t; | |||
342 | } else { | |||
343 | register_new_node( phi_post, prior_n ); | |||
344 | } | |||
345 | } | |||
346 | } | |||
347 | ||||
348 | // Update cache everywhere | |||
349 | prior_n = (Node*)((intptr_t)0xdeadbeef); // Reset IDOM walk | |||
350 | n = use_blk; // Get path input | |||
351 | // Spin-up the idom tree again, basically doing path-compression. | |||
352 | // Insert cache entries along the way, so that if we ever hit this | |||
353 | // point in the IDOM tree again we'll stop immediately on a cache hit. | |||
354 | while( n != iff_dom ) { // Found post-dominating point? | |||
355 | prior_n = n; | |||
356 | n = idom(n); // Search higher | |||
357 | cache->lru_insert( prior_n, phi_post ); // Fill cache | |||
358 | } // End of while not gone high enough | |||
359 | ||||
360 | return phi_post; | |||
361 | } | |||
362 | ||||
363 | //------------------------------find_use_block--------------------------------- | |||
364 | // Find the block a USE is in. Normally USE's are in the same block as the | |||
365 | // using instruction. For Phi-USE's, the USE is in the predecessor block | |||
366 | // along the corresponding path. | |||
367 | Node *PhaseIdealLoop::find_use_block( Node *use, Node *def, Node *old_false, Node *new_false, Node *old_true, Node *new_true ) { | |||
368 | // CFG uses are their own block | |||
369 | if( use->is_CFG() ) | |||
370 | return use; | |||
371 | ||||
372 | if( use->is_Phi() ) { // Phi uses in prior block | |||
373 | // Grab the first Phi use; there may be many. | |||
374 | // Each will be handled as a separate iteration of | |||
375 | // the "while( phi->outcnt() )" loop. | |||
376 | uint j; | |||
377 | for( j = 1; j < use->req(); j++ ) | |||
378 | if( use->in(j) == def ) | |||
379 | break; | |||
380 | assert( j < use->req(), "def should be among use's inputs" )do { if (!(j < use->req())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 380, "assert(" "j < use->req()" ") failed", "def should be among use's inputs" ); ::breakpoint(); } } while (0); | |||
381 | return use->in(0)->in(j); | |||
382 | } | |||
383 | // Normal (non-phi) use | |||
384 | Node *use_blk = get_ctrl(use); | |||
385 | // Some uses are directly attached to the old (and going away) | |||
386 | // false and true branches. | |||
387 | if( use_blk == old_false ) { | |||
388 | use_blk = new_false; | |||
389 | set_ctrl(use, new_false); | |||
390 | } | |||
391 | if( use_blk == old_true ) { | |||
392 | use_blk = new_true; | |||
393 | set_ctrl(use, new_true); | |||
394 | } | |||
395 | ||||
396 | if (use_blk == NULL__null) { // He's dead, Jim | |||
397 | _igvn.replace_node(use, C->top()); | |||
398 | } | |||
399 | ||||
400 | return use_blk; | |||
401 | } | |||
402 | ||||
403 | //------------------------------handle_use------------------------------------- | |||
404 | // Handle uses of the merge point. Basically, split-if makes the merge point | |||
405 | // go away so all uses of the merge point must go away as well. Most block | |||
406 | // local uses have already been split-up, through the merge point. Uses from | |||
407 | // far below the merge point can't always be split up (e.g., phi-uses are | |||
408 | // pinned) and it makes too much stuff live. Instead we use a path-based | |||
409 | // solution to move uses down. | |||
410 | // | |||
411 | // If the use is along the pre-split-CFG true branch, then the new use will | |||
412 | // be from the post-split-CFG true merge point. Vice-versa for the false | |||
413 | // path. Some uses will be along both paths; then we sink the use to the | |||
414 | // post-dominating location; we may need to insert a Phi there. | |||
415 | void PhaseIdealLoop::handle_use( Node *use, Node *def, small_cache *cache, Node *region_dom, Node *new_false, Node *new_true, Node *old_false, Node *old_true ) { | |||
416 | ||||
417 | Node *use_blk = find_use_block(use,def,old_false,new_false,old_true,new_true); | |||
418 | if( !use_blk ) return; // He's dead, Jim | |||
419 | ||||
420 | // Walk up the dominator tree until I hit either the old IfFalse, the old | |||
421 | // IfTrue or the old If. Insert Phis where needed. | |||
422 | Node *new_def = spinup( region_dom, new_false, new_true, use_blk, def, cache ); | |||
423 | ||||
424 | // Found where this USE goes. Re-point him. | |||
425 | uint i; | |||
426 | for( i = 0; i < use->req(); i++ ) | |||
427 | if( use->in(i) == def ) | |||
428 | break; | |||
429 | assert( i < use->req(), "def should be among use's inputs" )do { if (!(i < use->req())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 429, "assert(" "i < use->req()" ") failed", "def should be among use's inputs" ); ::breakpoint(); } } while (0); | |||
430 | _igvn.replace_input_of(use, i, new_def); | |||
431 | } | |||
432 | ||||
433 | //------------------------------do_split_if------------------------------------ | |||
434 | // Found an If getting its condition-code input from a Phi in the same block. | |||
435 | // Split thru the Region. | |||
436 | void PhaseIdealLoop::do_split_if( Node *iff ) { | |||
437 | if (PrintOpto && VerifyLoopOptimizations) { | |||
438 | tty->print_cr("Split-if"); | |||
439 | } | |||
440 | if (TraceLoopOpts) { | |||
441 | tty->print_cr("SplitIf"); | |||
442 | } | |||
443 | ||||
444 | C->set_major_progress(); | |||
445 | Node *region = iff->in(0); | |||
446 | Node *region_dom = idom(region); | |||
447 | ||||
448 | // We are going to clone this test (and the control flow with it) up through | |||
449 | // the incoming merge point. We need to empty the current basic block. | |||
450 | // Clone any instructions which must be in this block up through the merge | |||
451 | // point. | |||
452 | DUIterator i, j; | |||
453 | bool progress = true; | |||
454 | while (progress) { | |||
455 | progress = false; | |||
456 | for (i = region->outs(); region->has_out(i); i++) { | |||
457 | Node* n = region->out(i); | |||
458 | if( n == region ) continue; | |||
459 | // The IF to be split is OK. | |||
460 | if( n == iff ) continue; | |||
461 | if( !n->is_Phi() ) { // Found pinned memory op or such | |||
462 | if (split_up(n, region, iff)) { | |||
463 | i = region->refresh_out_pos(i); | |||
464 | progress = true; | |||
465 | } | |||
466 | continue; | |||
467 | } | |||
468 | assert( n->in(0) == region, "" )do { if (!(n->in(0) == region)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 468, "assert(" "n->in(0) == region" ") failed", ""); ::breakpoint (); } } while (0); | |||
469 | ||||
470 | // Recursively split up all users of a Phi | |||
471 | for (j = n->outs(); n->has_out(j); j++) { | |||
472 | Node* m = n->out(j); | |||
473 | // If m is dead, throw it away, and declare progress | |||
474 | if (_nodes[m->_idx] == NULL__null) { | |||
475 | _igvn.remove_dead_node(m); | |||
476 | // fall through | |||
477 | } | |||
478 | else if (m != iff && split_up(m, region, iff)) { | |||
479 | // fall through | |||
480 | } else { | |||
481 | continue; | |||
482 | } | |||
483 | // Something unpredictable changed. | |||
484 | // Tell the iterators to refresh themselves, and rerun the loop. | |||
485 | i = region->refresh_out_pos(i); | |||
486 | j = region->refresh_out_pos(j); | |||
487 | progress = true; | |||
488 | } | |||
489 | } | |||
490 | } | |||
491 | ||||
492 | // Now we have no instructions in the block containing the IF. | |||
493 | // Split the IF. | |||
494 | Node *new_iff = split_thru_region( iff, region ); | |||
495 | ||||
496 | // Replace both uses of 'new_iff' with Regions merging True/False | |||
497 | // paths. This makes 'new_iff' go dead. | |||
498 | Node *old_false = NULL__null, *old_true = NULL__null; | |||
499 | Node *new_false = NULL__null, *new_true = NULL__null; | |||
500 | for (DUIterator_Last j2min, j2 = iff->last_outs(j2min); j2 >= j2min; --j2) { | |||
501 | Node *ifp = iff->last_out(j2); | |||
502 | assert( ifp->Opcode() == Op_IfFalse || ifp->Opcode() == Op_IfTrue, "" )do { if (!(ifp->Opcode() == Op_IfFalse || ifp->Opcode() == Op_IfTrue)) { (*g_assert_poison) = 'X';; report_vm_error( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 502, "assert(" "ifp->Opcode() == Op_IfFalse || ifp->Opcode() == Op_IfTrue" ") failed", ""); ::breakpoint(); } } while (0); | |||
503 | ifp->set_req(0, new_iff); | |||
504 | Node *ifpx = split_thru_region( ifp, region ); | |||
505 | ||||
506 | // Replace 'If' projection of a Region with a Region of | |||
507 | // 'If' projections. | |||
508 | ifpx->set_req(0, ifpx); // A TRUE RegionNode | |||
509 | ||||
510 | // Setup dominator info | |||
511 | set_idom(ifpx, region_dom, dom_depth(region_dom) + 1); | |||
512 | ||||
513 | // Check for splitting loop tails | |||
514 | if( get_loop(iff)->tail() == ifp ) | |||
515 | get_loop(iff)->_tail = ifpx; | |||
516 | ||||
517 | // Replace in the graph with lazy-update mechanism | |||
518 | new_iff->set_req(0, new_iff); // hook self so it does not go dead | |||
519 | lazy_replace(ifp, ifpx); | |||
520 | new_iff->set_req(0, region); | |||
521 | ||||
522 | // Record bits for later xforms | |||
523 | if( ifp->Opcode() == Op_IfFalse ) { | |||
524 | old_false = ifp; | |||
525 | new_false = ifpx; | |||
526 | } else { | |||
527 | old_true = ifp; | |||
528 | new_true = ifpx; | |||
529 | } | |||
530 | } | |||
531 | _igvn.remove_dead_node(new_iff); | |||
532 | // Lazy replace IDOM info with the region's dominator | |||
533 | lazy_replace(iff, region_dom); | |||
534 | lazy_update(region, region_dom); // idom must be update before handle_uses | |||
535 | region->set_req(0, NULL__null); // Break the self-cycle. Required for lazy_update to work on region | |||
536 | ||||
537 | // Now make the original merge point go dead, by handling all its uses. | |||
538 | small_cache region_cache; | |||
539 | // Preload some control flow in region-cache | |||
540 | region_cache.lru_insert( new_false, new_false ); | |||
541 | region_cache.lru_insert( new_true , new_true ); | |||
542 | // Now handle all uses of the splitting block | |||
543 | for (DUIterator k = region->outs(); region->has_out(k); k++) { | |||
544 | Node* phi = region->out(k); | |||
545 | if (!phi->in(0)) { // Dead phi? Remove it | |||
546 | _igvn.remove_dead_node(phi); | |||
547 | } else if (phi == region) { // Found the self-reference | |||
548 | continue; // No roll-back of DUIterator | |||
549 | } else if (phi->is_Phi()) { // Expected common case: Phi hanging off of Region | |||
550 | assert(phi->in(0) == region, "Inconsistent graph")do { if (!(phi->in(0) == region)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 550, "assert(" "phi->in(0) == region" ") failed", "Inconsistent graph" ); ::breakpoint(); } } while (0); | |||
551 | // Need a per-def cache. Phi represents a def, so make a cache | |||
552 | small_cache phi_cache; | |||
553 | ||||
554 | // Inspect all Phi uses to make the Phi go dead | |||
555 | for (DUIterator_Last lmin, l = phi->last_outs(lmin); l >= lmin; --l) { | |||
556 | Node* use = phi->last_out(l); | |||
557 | // Compute the new DEF for this USE. New DEF depends on the path | |||
558 | // taken from the original DEF to the USE. The new DEF may be some | |||
559 | // collection of PHI's merging values from different paths. The Phis | |||
560 | // inserted depend only on the location of the USE. We use a | |||
561 | // 2-element cache to handle multiple uses from the same block. | |||
562 | handle_use(use, phi, &phi_cache, region_dom, new_false, new_true, old_false, old_true); | |||
563 | } // End of while phi has uses | |||
564 | // Remove the dead Phi | |||
565 | _igvn.remove_dead_node( phi ); | |||
566 | } else { | |||
567 | assert(phi->in(0) == region, "Inconsistent graph")do { if (!(phi->in(0) == region)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/split_if.cpp" , 567, "assert(" "phi->in(0) == region" ") failed", "Inconsistent graph" ); ::breakpoint(); } } while (0); | |||
568 | // Random memory op guarded by Region. Compute new DEF for USE. | |||
569 | handle_use(phi, region, ®ion_cache, region_dom, new_false, new_true, old_false, old_true); | |||
570 | } | |||
571 | // Every path above deletes a use of the region, except for the region | |||
572 | // self-cycle (which is needed by handle_use calling find_use_block | |||
573 | // calling get_ctrl calling get_ctrl_no_update looking for dead | |||
574 | // regions). So roll back the DUIterator innards. | |||
575 | --k; | |||
576 | } // End of while merge point has phis | |||
577 | ||||
578 | _igvn.remove_dead_node(region); | |||
579 | ||||
580 | #ifndef PRODUCT | |||
581 | if( VerifyLoopOptimizations ) verify(); | |||
582 | #endif | |||
583 | } |
1 | /* |
2 | * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. |
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 | * |
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
20 | * or visit www.oracle.com if you need additional information or have any |
21 | * questions. |
22 | * |
23 | */ |
24 | |
25 | #ifndef SHARE_OPTO_NODE_HPP |
26 | #define SHARE_OPTO_NODE_HPP |
27 | |
28 | #include "libadt/vectset.hpp" |
29 | #include "opto/compile.hpp" |
30 | #include "opto/type.hpp" |
31 | #include "utilities/copy.hpp" |
32 | |
33 | // Portions of code courtesy of Clifford Click |
34 | |
35 | // Optimization - Graph Style |
36 | |
37 | |
38 | class AbstractLockNode; |
39 | class AddNode; |
40 | class AddPNode; |
41 | class AliasInfo; |
42 | class AllocateArrayNode; |
43 | class AllocateNode; |
44 | class ArrayCopyNode; |
45 | class BaseCountedLoopNode; |
46 | class BaseCountedLoopEndNode; |
47 | class BlackholeNode; |
48 | class Block; |
49 | class BoolNode; |
50 | class BoxLockNode; |
51 | class CMoveNode; |
52 | class CallDynamicJavaNode; |
53 | class CallJavaNode; |
54 | class CallLeafNode; |
55 | class CallLeafNoFPNode; |
56 | class CallNode; |
57 | class CallRuntimeNode; |
58 | class CallNativeNode; |
59 | class CallStaticJavaNode; |
60 | class CastFFNode; |
61 | class CastDDNode; |
62 | class CastVVNode; |
63 | class CastIINode; |
64 | class CastLLNode; |
65 | class CatchNode; |
66 | class CatchProjNode; |
67 | class CheckCastPPNode; |
68 | class ClearArrayNode; |
69 | class CmpNode; |
70 | class CodeBuffer; |
71 | class ConstraintCastNode; |
72 | class ConNode; |
73 | class CompareAndSwapNode; |
74 | class CompareAndExchangeNode; |
75 | class CountedLoopNode; |
76 | class CountedLoopEndNode; |
77 | class DecodeNarrowPtrNode; |
78 | class DecodeNNode; |
79 | class DecodeNKlassNode; |
80 | class EncodeNarrowPtrNode; |
81 | class EncodePNode; |
82 | class EncodePKlassNode; |
83 | class FastLockNode; |
84 | class FastUnlockNode; |
85 | class HaltNode; |
86 | class IfNode; |
87 | class IfProjNode; |
88 | class IfFalseNode; |
89 | class IfTrueNode; |
90 | class InitializeNode; |
91 | class JVMState; |
92 | class JumpNode; |
93 | class JumpProjNode; |
94 | class LoadNode; |
95 | class LoadStoreNode; |
96 | class LoadStoreConditionalNode; |
97 | class LockNode; |
98 | class LongCountedLoopNode; |
99 | class LongCountedLoopEndNode; |
100 | class LoopNode; |
101 | class LShiftNode; |
102 | class MachBranchNode; |
103 | class MachCallDynamicJavaNode; |
104 | class MachCallJavaNode; |
105 | class MachCallLeafNode; |
106 | class MachCallNode; |
107 | class MachCallNativeNode; |
108 | class MachCallRuntimeNode; |
109 | class MachCallStaticJavaNode; |
110 | class MachConstantBaseNode; |
111 | class MachConstantNode; |
112 | class MachGotoNode; |
113 | class MachIfNode; |
114 | class MachJumpNode; |
115 | class MachNode; |
116 | class MachNullCheckNode; |
117 | class MachProjNode; |
118 | class MachReturnNode; |
119 | class MachSafePointNode; |
120 | class MachSpillCopyNode; |
121 | class MachTempNode; |
122 | class MachMergeNode; |
123 | class MachMemBarNode; |
124 | class Matcher; |
125 | class MemBarNode; |
126 | class MemBarStoreStoreNode; |
127 | class MemNode; |
128 | class MergeMemNode; |
129 | class MoveNode; |
130 | class MulNode; |
131 | class MultiNode; |
132 | class MultiBranchNode; |
133 | class NeverBranchNode; |
134 | class Opaque1Node; |
135 | class OuterStripMinedLoopNode; |
136 | class OuterStripMinedLoopEndNode; |
137 | class Node; |
138 | class Node_Array; |
139 | class Node_List; |
140 | class Node_Stack; |
141 | class OopMap; |
142 | class ParmNode; |
143 | class PCTableNode; |
144 | class PhaseCCP; |
145 | class PhaseGVN; |
146 | class PhaseIterGVN; |
147 | class PhaseRegAlloc; |
148 | class PhaseTransform; |
149 | class PhaseValues; |
150 | class PhiNode; |
151 | class Pipeline; |
152 | class ProjNode; |
153 | class RangeCheckNode; |
154 | class RegMask; |
155 | class RegionNode; |
156 | class RootNode; |
157 | class SafePointNode; |
158 | class SafePointScalarObjectNode; |
159 | class StartNode; |
160 | class State; |
161 | class StoreNode; |
162 | class SubNode; |
163 | class SubTypeCheckNode; |
164 | class Type; |
165 | class TypeNode; |
166 | class UnlockNode; |
167 | class VectorNode; |
168 | class LoadVectorNode; |
169 | class LoadVectorMaskedNode; |
170 | class StoreVectorMaskedNode; |
171 | class LoadVectorGatherNode; |
172 | class StoreVectorNode; |
173 | class StoreVectorScatterNode; |
174 | class VectorMaskCmpNode; |
175 | class VectorUnboxNode; |
176 | class VectorSet; |
177 | class VectorReinterpretNode; |
178 | class ShiftVNode; |
179 | |
180 | // The type of all node counts and indexes. |
181 | // It must hold at least 16 bits, but must also be fast to load and store. |
182 | // This type, if less than 32 bits, could limit the number of possible nodes. |
183 | // (To make this type platform-specific, move to globalDefinitions_xxx.hpp.) |
184 | typedef unsigned int node_idx_t; |
185 | |
186 | |
187 | #ifndef OPTO_DU_ITERATOR_ASSERT1 |
188 | #ifdef ASSERT1 |
189 | #define OPTO_DU_ITERATOR_ASSERT1 1 |
190 | #else |
191 | #define OPTO_DU_ITERATOR_ASSERT1 0 |
192 | #endif |
193 | #endif //OPTO_DU_ITERATOR_ASSERT |
194 | |
195 | #if OPTO_DU_ITERATOR_ASSERT1 |
196 | class DUIterator; |
197 | class DUIterator_Fast; |
198 | class DUIterator_Last; |
199 | #else |
200 | typedef uint DUIterator; |
201 | typedef Node** DUIterator_Fast; |
202 | typedef Node** DUIterator_Last; |
203 | #endif |
204 | |
205 | // Node Sentinel |
206 | #define NodeSentinel(Node*)-1 (Node*)-1 |
207 | |
208 | // Unknown count frequency |
209 | #define COUNT_UNKNOWN(-1.0f) (-1.0f) |
210 | |
211 | //------------------------------Node------------------------------------------- |
212 | // Nodes define actions in the program. They create values, which have types. |
213 | // They are both vertices in a directed graph and program primitives. Nodes |
214 | // are labeled; the label is the "opcode", the primitive function in the lambda |
215 | // calculus sense that gives meaning to the Node. Node inputs are ordered (so |
216 | // that "a-b" is different from "b-a"). The inputs to a Node are the inputs to |
217 | // the Node's function. These inputs also define a Type equation for the Node. |
218 | // Solving these Type equations amounts to doing dataflow analysis. |
219 | // Control and data are uniformly represented in the graph. Finally, Nodes |
220 | // have a unique dense integer index which is used to index into side arrays |
221 | // whenever I have phase-specific information. |
222 | |
223 | class Node { |
224 | friend class VMStructs; |
225 | |
226 | // Lots of restrictions on cloning Nodes |
227 | NONCOPYABLE(Node)Node(Node const&) = delete; Node& operator=(Node const &) = delete; |
228 | |
229 | public: |
230 | friend class Compile; |
231 | #if OPTO_DU_ITERATOR_ASSERT1 |
232 | friend class DUIterator_Common; |
233 | friend class DUIterator; |
234 | friend class DUIterator_Fast; |
235 | friend class DUIterator_Last; |
236 | #endif |
237 | |
238 | // Because Nodes come and go, I define an Arena of Node structures to pull |
239 | // from. This should allow fast access to node creation & deletion. This |
240 | // field is a local cache of a value defined in some "program fragment" for |
241 | // which these Nodes are just a part of. |
242 | |
243 | inline void* operator new(size_t x) throw() { |
244 | Compile* C = Compile::current(); |
245 | Node* n = (Node*)C->node_arena()->AmallocWords(x); |
246 | return (void*)n; |
247 | } |
248 | |
249 | // Delete is a NOP |
250 | void operator delete( void *ptr ) {} |
251 | // Fancy destructor; eagerly attempt to reclaim Node numberings and storage |
252 | void destruct(PhaseValues* phase); |
253 | |
254 | // Create a new Node. Required is the number is of inputs required for |
255 | // semantic correctness. |
256 | Node( uint required ); |
257 | |
258 | // Create a new Node with given input edges. |
259 | // This version requires use of the "edge-count" new. |
260 | // E.g. new (C,3) FooNode( C, NULL, left, right ); |
261 | Node( Node *n0 ); |
262 | Node( Node *n0, Node *n1 ); |
263 | Node( Node *n0, Node *n1, Node *n2 ); |
264 | Node( Node *n0, Node *n1, Node *n2, Node *n3 ); |
265 | Node( Node *n0, Node *n1, Node *n2, Node *n3, Node *n4 ); |
266 | Node( Node *n0, Node *n1, Node *n2, Node *n3, Node *n4, Node *n5 ); |
267 | Node( Node *n0, Node *n1, Node *n2, Node *n3, |
268 | Node *n4, Node *n5, Node *n6 ); |
269 | |
270 | // Clone an inherited Node given only the base Node type. |
271 | Node* clone() const; |
272 | |
273 | // Clone a Node, immediately supplying one or two new edges. |
274 | // The first and second arguments, if non-null, replace in(1) and in(2), |
275 | // respectively. |
276 | Node* clone_with_data_edge(Node* in1, Node* in2 = NULL__null) const { |
277 | Node* nn = clone(); |
278 | if (in1 != NULL__null) nn->set_req(1, in1); |
279 | if (in2 != NULL__null) nn->set_req(2, in2); |
280 | return nn; |
281 | } |
282 | |
283 | private: |
284 | // Shared setup for the above constructors. |
285 | // Handles all interactions with Compile::current. |
286 | // Puts initial values in all Node fields except _idx. |
287 | // Returns the initial value for _idx, which cannot |
288 | // be initialized by assignment. |
289 | inline int Init(int req); |
290 | |
291 | //----------------- input edge handling |
292 | protected: |
293 | friend class PhaseCFG; // Access to address of _in array elements |
294 | Node **_in; // Array of use-def references to Nodes |
295 | Node **_out; // Array of def-use references to Nodes |
296 | |
297 | // Input edges are split into two categories. Required edges are required |
298 | // for semantic correctness; order is important and NULLs are allowed. |
299 | // Precedence edges are used to help determine execution order and are |
300 | // added, e.g., for scheduling purposes. They are unordered and not |
301 | // duplicated; they have no embedded NULLs. Edges from 0 to _cnt-1 |
302 | // are required, from _cnt to _max-1 are precedence edges. |
303 | node_idx_t _cnt; // Total number of required Node inputs. |
304 | |
305 | node_idx_t _max; // Actual length of input array. |
306 | |
307 | // Output edges are an unordered list of def-use edges which exactly |
308 | // correspond to required input edges which point from other nodes |
309 | // to this one. Thus the count of the output edges is the number of |
310 | // users of this node. |
311 | node_idx_t _outcnt; // Total number of Node outputs. |
312 | |
313 | node_idx_t _outmax; // Actual length of output array. |
314 | |
315 | // Grow the actual input array to the next larger power-of-2 bigger than len. |
316 | void grow( uint len ); |
317 | // Grow the output array to the next larger power-of-2 bigger than len. |
318 | void out_grow( uint len ); |
319 | |
320 | public: |
321 | // Each Node is assigned a unique small/dense number. This number is used |
322 | // to index into auxiliary arrays of data and bit vectors. |
323 | // The field _idx is declared constant to defend against inadvertent assignments, |
324 | // since it is used by clients as a naked field. However, the field's value can be |
325 | // changed using the set_idx() method. |
326 | // |
327 | // The PhaseRenumberLive phase renumbers nodes based on liveness information. |
328 | // Therefore, it updates the value of the _idx field. The parse-time _idx is |
329 | // preserved in _parse_idx. |
330 | const node_idx_t _idx; |
331 | DEBUG_ONLY(const node_idx_t _parse_idx;)const node_idx_t _parse_idx; |
332 | // IGV node identifier. Two nodes, possibly in different compilation phases, |
333 | // have the same IGV identifier if (and only if) they are the very same node |
334 | // (same memory address) or one is "derived" from the other (by e.g. |
335 | // renumbering or matching). This identifier makes it possible to follow the |
336 | // entire lifetime of a node in IGV even if its C2 identifier (_idx) changes. |
337 | NOT_PRODUCT(node_idx_t _igv_idx;)node_idx_t _igv_idx; |
338 | |
339 | // Get the (read-only) number of input edges |
340 | uint req() const { return _cnt; } |
341 | uint len() const { return _max; } |
342 | // Get the (read-only) number of output edges |
343 | uint outcnt() const { return _outcnt; } |
344 | |
345 | #if OPTO_DU_ITERATOR_ASSERT1 |
346 | // Iterate over the out-edges of this node. Deletions are illegal. |
347 | inline DUIterator outs() const; |
348 | // Use this when the out array might have changed to suppress asserts. |
349 | inline DUIterator& refresh_out_pos(DUIterator& i) const; |
350 | // Does the node have an out at this position? (Used for iteration.) |
351 | inline bool has_out(DUIterator& i) const; |
352 | inline Node* out(DUIterator& i) const; |
353 | // Iterate over the out-edges of this node. All changes are illegal. |
354 | inline DUIterator_Fast fast_outs(DUIterator_Fast& max) const; |
355 | inline Node* fast_out(DUIterator_Fast& i) const; |
356 | // Iterate over the out-edges of this node, deleting one at a time. |
357 | inline DUIterator_Last last_outs(DUIterator_Last& min) const; |
358 | inline Node* last_out(DUIterator_Last& i) const; |
359 | // The inline bodies of all these methods are after the iterator definitions. |
360 | #else |
361 | // Iterate over the out-edges of this node. Deletions are illegal. |
362 | // This iteration uses integral indexes, to decouple from array reallocations. |
363 | DUIterator outs() const { return 0; } |
364 | // Use this when the out array might have changed to suppress asserts. |
365 | DUIterator refresh_out_pos(DUIterator i) const { return i; } |
366 | |
367 | // Reference to the i'th output Node. Error if out of bounds. |
368 | Node* out(DUIterator i) const { assert(i < _outcnt, "oob")do { if (!(i < _outcnt)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 368, "assert(" "i < _outcnt" ") failed", "oob"); ::breakpoint (); } } while (0); return _out[i]; } |
369 | // Does the node have an out at this position? (Used for iteration.) |
370 | bool has_out(DUIterator i) const { return i < _outcnt; } |
371 | |
372 | // Iterate over the out-edges of this node. All changes are illegal. |
373 | // This iteration uses a pointer internal to the out array. |
374 | DUIterator_Fast fast_outs(DUIterator_Fast& max) const { |
375 | Node** out = _out; |
376 | // Assign a limit pointer to the reference argument: |
377 | max = out + (ptrdiff_t)_outcnt; |
378 | // Return the base pointer: |
379 | return out; |
380 | } |
381 | Node* fast_out(DUIterator_Fast i) const { return *i; } |
382 | // Iterate over the out-edges of this node, deleting one at a time. |
383 | // This iteration uses a pointer internal to the out array. |
384 | DUIterator_Last last_outs(DUIterator_Last& min) const { |
385 | Node** out = _out; |
386 | // Assign a limit pointer to the reference argument: |
387 | min = out; |
388 | // Return the pointer to the start of the iteration: |
389 | return out + (ptrdiff_t)_outcnt - 1; |
390 | } |
391 | Node* last_out(DUIterator_Last i) const { return *i; } |
392 | #endif |
393 | |
394 | // Reference to the i'th input Node. Error if out of bounds. |
395 | Node* in(uint i) const { assert(i < _max, "oob: i=%d, _max=%d", i, _max)do { if (!(i < _max)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 395, "assert(" "i < _max" ") failed", "oob: i=%d, _max=%d" , i, _max); ::breakpoint(); } } while (0); return _in[i]; } |
396 | // Reference to the i'th input Node. NULL if out of bounds. |
397 | Node* lookup(uint i) const { return ((i < _max) ? _in[i] : NULL__null); } |
398 | // Reference to the i'th output Node. Error if out of bounds. |
399 | // Use this accessor sparingly. We are going trying to use iterators instead. |
400 | Node* raw_out(uint i) const { assert(i < _outcnt,"oob")do { if (!(i < _outcnt)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 400, "assert(" "i < _outcnt" ") failed", "oob"); ::breakpoint (); } } while (0); return _out[i]; } |
401 | // Return the unique out edge. |
402 | Node* unique_out() const { assert(_outcnt==1,"not unique")do { if (!(_outcnt==1)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 402, "assert(" "_outcnt==1" ") failed", "not unique"); ::breakpoint (); } } while (0); return _out[0]; } |
403 | // Delete out edge at position 'i' by moving last out edge to position 'i' |
404 | void raw_del_out(uint i) { |
405 | assert(i < _outcnt,"oob")do { if (!(i < _outcnt)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 405, "assert(" "i < _outcnt" ") failed", "oob"); ::breakpoint (); } } while (0); |
406 | assert(_outcnt > 0,"oob")do { if (!(_outcnt > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 406, "assert(" "_outcnt > 0" ") failed", "oob"); ::breakpoint (); } } while (0); |
407 | #if OPTO_DU_ITERATOR_ASSERT1 |
408 | // Record that a change happened here. |
409 | debug_only(_last_del = _out[i]; ++_del_tick)_last_del = _out[i]; ++_del_tick; |
410 | #endif |
411 | _out[i] = _out[--_outcnt]; |
412 | // Smash the old edge so it can't be used accidentally. |
413 | debug_only(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef)_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef; |
414 | } |
415 | |
416 | #ifdef ASSERT1 |
417 | bool is_dead() const; |
418 | #define is_not_dead(n)((n) == __null || !VerifyIterativeGVN || !((n)->is_dead()) ) ((n) == NULL__null || !VerifyIterativeGVN || !((n)->is_dead())) |
419 | bool is_reachable_from_root() const; |
420 | #endif |
421 | // Check whether node has become unreachable |
422 | bool is_unreachable(PhaseIterGVN &igvn) const; |
423 | |
424 | // Set a required input edge, also updates corresponding output edge |
425 | void add_req( Node *n ); // Append a NEW required input |
426 | void add_req( Node *n0, Node *n1 ) { |
427 | add_req(n0); add_req(n1); } |
428 | void add_req( Node *n0, Node *n1, Node *n2 ) { |
429 | add_req(n0); add_req(n1); add_req(n2); } |
430 | void add_req_batch( Node* n, uint m ); // Append m NEW required inputs (all n). |
431 | void del_req( uint idx ); // Delete required edge & compact |
432 | void del_req_ordered( uint idx ); // Delete required edge & compact with preserved order |
433 | void ins_req( uint i, Node *n ); // Insert a NEW required input |
434 | void set_req( uint i, Node *n ) { |
435 | assert( is_not_dead(n), "can not use dead node")do { if (!(((n) == __null || !VerifyIterativeGVN || !((n)-> is_dead())))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 435, "assert(" "((n) == __null || !VerifyIterativeGVN || !((n)->is_dead()))" ") failed", "can not use dead node"); ::breakpoint(); } } while (0); |
436 | assert( i < _cnt, "oob: i=%d, _cnt=%d", i, _cnt)do { if (!(i < _cnt)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 436, "assert(" "i < _cnt" ") failed", "oob: i=%d, _cnt=%d" , i, _cnt); ::breakpoint(); } } while (0); |
437 | assert( !VerifyHashTableKeys || _hash_lock == 0,do { if (!(!VerifyHashTableKeys || _hash_lock == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 438, "assert(" "!VerifyHashTableKeys || _hash_lock == 0" ") failed" , "remove node from hash table before modifying it"); ::breakpoint (); } } while (0) |
438 | "remove node from hash table before modifying it")do { if (!(!VerifyHashTableKeys || _hash_lock == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 438, "assert(" "!VerifyHashTableKeys || _hash_lock == 0" ") failed" , "remove node from hash table before modifying it"); ::breakpoint (); } } while (0); |
439 | Node** p = &_in[i]; // cache this._in, across the del_out call |
440 | if (*p != NULL__null) (*p)->del_out((Node *)this); |
441 | (*p) = n; |
442 | if (n != NULL__null) n->add_out((Node *)this); |
443 | Compile::current()->record_modified_node(this); |
444 | } |
445 | // Light version of set_req() to init inputs after node creation. |
446 | void init_req( uint i, Node *n ) { |
447 | assert( i == 0 && this == n ||do { if (!(i == 0 && this == n || ((n) == __null || ! VerifyIterativeGVN || !((n)->is_dead())))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 448, "assert(" "i == 0 && this == n || ((n) == __null || !VerifyIterativeGVN || !((n)->is_dead()))" ") failed", "can not use dead node"); ::breakpoint(); } } while (0) |
448 | is_not_dead(n), "can not use dead node")do { if (!(i == 0 && this == n || ((n) == __null || ! VerifyIterativeGVN || !((n)->is_dead())))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 448, "assert(" "i == 0 && this == n || ((n) == __null || !VerifyIterativeGVN || !((n)->is_dead()))" ") failed", "can not use dead node"); ::breakpoint(); } } while (0); |
449 | assert( i < _cnt, "oob")do { if (!(i < _cnt)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 449, "assert(" "i < _cnt" ") failed", "oob"); ::breakpoint (); } } while (0); |
450 | assert( !VerifyHashTableKeys || _hash_lock == 0,do { if (!(!VerifyHashTableKeys || _hash_lock == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 451, "assert(" "!VerifyHashTableKeys || _hash_lock == 0" ") failed" , "remove node from hash table before modifying it"); ::breakpoint (); } } while (0) |
451 | "remove node from hash table before modifying it")do { if (!(!VerifyHashTableKeys || _hash_lock == 0)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 451, "assert(" "!VerifyHashTableKeys || _hash_lock == 0" ") failed" , "remove node from hash table before modifying it"); ::breakpoint (); } } while (0); |
452 | assert( _in[i] == NULL, "sanity")do { if (!(_in[i] == __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 452, "assert(" "_in[i] == __null" ") failed", "sanity"); :: breakpoint(); } } while (0); |
453 | _in[i] = n; |
454 | if (n != NULL__null) n->add_out((Node *)this); |
455 | Compile::current()->record_modified_node(this); |
456 | } |
457 | // Find first occurrence of n among my edges: |
458 | int find_edge(Node* n); |
459 | int find_prec_edge(Node* n) { |
460 | for (uint i = req(); i < len(); i++) { |
461 | if (_in[i] == n) return i; |
462 | if (_in[i] == NULL__null) { |
463 | DEBUG_ONLY( while ((++i) < len()) assert(_in[i] == NULL, "Gap in prec edges!"); )while ((++i) < len()) do { if (!(_in[i] == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 463, "assert(" "_in[i] == __null" ") failed", "Gap in prec edges!" ); ::breakpoint(); } } while (0); |
464 | break; |
465 | } |
466 | } |
467 | return -1; |
468 | } |
469 | int replace_edge(Node* old, Node* neww, PhaseGVN* gvn = NULL__null); |
470 | int replace_edges_in_range(Node* old, Node* neww, int start, int end, PhaseGVN* gvn); |
471 | // NULL out all inputs to eliminate incoming Def-Use edges. |
472 | void disconnect_inputs(Compile* C); |
473 | |
474 | // Quickly, return true if and only if I am Compile::current()->top(). |
475 | bool is_top() const { |
476 | assert((this == (Node*) Compile::current()->top()) == (_out == NULL), "")do { if (!((this == (Node*) Compile::current()->top()) == ( _out == __null))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 476, "assert(" "(this == (Node*) Compile::current()->top()) == (_out == __null)" ") failed", ""); ::breakpoint(); } } while (0); |
477 | return (_out == NULL__null); |
478 | } |
479 | // Reaffirm invariants for is_top. (Only from Compile::set_cached_top_node.) |
480 | void setup_is_top(); |
481 | |
482 | // Strip away casting. (It is depth-limited.) |
483 | Node* uncast(bool keep_deps = false) const; |
484 | // Return whether two Nodes are equivalent, after stripping casting. |
485 | bool eqv_uncast(const Node* n, bool keep_deps = false) const { |
486 | return (this->uncast(keep_deps) == n->uncast(keep_deps)); |
487 | } |
488 | |
489 | // Find out of current node that matches opcode. |
490 | Node* find_out_with(int opcode); |
491 | // Return true if the current node has an out that matches opcode. |
492 | bool has_out_with(int opcode); |
493 | // Return true if the current node has an out that matches any of the opcodes. |
494 | bool has_out_with(int opcode1, int opcode2, int opcode3, int opcode4); |
495 | |
496 | private: |
497 | static Node* uncast_helper(const Node* n, bool keep_deps); |
498 | |
499 | // Add an output edge to the end of the list |
500 | void add_out( Node *n ) { |
501 | if (is_top()) return; |
502 | if( _outcnt == _outmax ) out_grow(_outcnt); |
503 | _out[_outcnt++] = n; |
504 | } |
505 | // Delete an output edge |
506 | void del_out( Node *n ) { |
507 | if (is_top()) return; |
508 | Node** outp = &_out[_outcnt]; |
509 | // Find and remove n |
510 | do { |
511 | assert(outp > _out, "Missing Def-Use edge")do { if (!(outp > _out)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 511, "assert(" "outp > _out" ") failed", "Missing Def-Use edge" ); ::breakpoint(); } } while (0); |
512 | } while (*--outp != n); |
513 | *outp = _out[--_outcnt]; |
514 | // Smash the old edge so it can't be used accidentally. |
515 | debug_only(_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef)_out[_outcnt] = (Node *)(uintptr_t)0xdeadbeef; |
516 | // Record that a change happened here. |
517 | #if OPTO_DU_ITERATOR_ASSERT1 |
518 | debug_only(_last_del = n; ++_del_tick)_last_del = n; ++_del_tick; |
519 | #endif |
520 | } |
521 | // Close gap after removing edge. |
522 | void close_prec_gap_at(uint gap) { |
523 | assert(_cnt <= gap && gap < _max, "no valid prec edge")do { if (!(_cnt <= gap && gap < _max)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 523, "assert(" "_cnt <= gap && gap < _max" ") failed" , "no valid prec edge"); ::breakpoint(); } } while (0); |
524 | uint i = gap; |
525 | Node *last = NULL__null; |
526 | for (; i < _max-1; ++i) { |
527 | Node *next = _in[i+1]; |
528 | if (next == NULL__null) break; |
529 | last = next; |
530 | } |
531 | _in[gap] = last; // Move last slot to empty one. |
532 | _in[i] = NULL__null; // NULL out last slot. |
533 | } |
534 | |
535 | public: |
536 | // Globally replace this node by a given new node, updating all uses. |
537 | void replace_by(Node* new_node); |
538 | // Globally replace this node by a given new node, updating all uses |
539 | // and cutting input edges of old node. |
540 | void subsume_by(Node* new_node, Compile* c) { |
541 | replace_by(new_node); |
542 | disconnect_inputs(c); |
543 | } |
544 | void set_req_X(uint i, Node *n, PhaseIterGVN *igvn); |
545 | void set_req_X(uint i, Node *n, PhaseGVN *gvn); |
546 | // Find the one non-null required input. RegionNode only |
547 | Node *nonnull_req() const; |
548 | // Add or remove precedence edges |
549 | void add_prec( Node *n ); |
550 | void rm_prec( uint i ); |
551 | |
552 | // Note: prec(i) will not necessarily point to n if edge already exists. |
553 | void set_prec( uint i, Node *n ) { |
554 | assert(i < _max, "oob: i=%d, _max=%d", i, _max)do { if (!(i < _max)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 554, "assert(" "i < _max" ") failed", "oob: i=%d, _max=%d" , i, _max); ::breakpoint(); } } while (0); |
555 | assert(is_not_dead(n), "can not use dead node")do { if (!(((n) == __null || !VerifyIterativeGVN || !((n)-> is_dead())))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 555, "assert(" "((n) == __null || !VerifyIterativeGVN || !((n)->is_dead()))" ") failed", "can not use dead node"); ::breakpoint(); } } while (0); |
556 | assert(i >= _cnt, "not a precedence edge")do { if (!(i >= _cnt)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 556, "assert(" "i >= _cnt" ") failed", "not a precedence edge" ); ::breakpoint(); } } while (0); |
557 | // Avoid spec violation: duplicated prec edge. |
558 | if (_in[i] == n) return; |
559 | if (n == NULL__null || find_prec_edge(n) != -1) { |
560 | rm_prec(i); |
561 | return; |
562 | } |
563 | if (_in[i] != NULL__null) _in[i]->del_out((Node *)this); |
564 | _in[i] = n; |
565 | n->add_out((Node *)this); |
566 | } |
567 | |
568 | // Set this node's index, used by cisc_version to replace current node |
569 | void set_idx(uint new_idx) { |
570 | const node_idx_t* ref = &_idx; |
571 | *(node_idx_t*)ref = new_idx; |
572 | } |
573 | // Swap input edge order. (Edge indexes i1 and i2 are usually 1 and 2.) |
574 | void swap_edges(uint i1, uint i2) { |
575 | debug_only(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH)uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH; |
576 | // Def-Use info is unchanged |
577 | Node* n1 = in(i1); |
578 | Node* n2 = in(i2); |
579 | _in[i1] = n2; |
580 | _in[i2] = n1; |
581 | // If this node is in the hash table, make sure it doesn't need a rehash. |
582 | assert(check_hash == NO_HASH || check_hash == hash(), "edge swap must preserve hash code")do { if (!(check_hash == NO_HASH || check_hash == hash())) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 582, "assert(" "check_hash == NO_HASH || check_hash == hash()" ") failed", "edge swap must preserve hash code"); ::breakpoint (); } } while (0); |
583 | } |
584 | |
585 | // Iterators over input Nodes for a Node X are written as: |
586 | // for( i = 0; i < X.req(); i++ ) ... X[i] ... |
587 | // NOTE: Required edges can contain embedded NULL pointers. |
588 | |
589 | //----------------- Other Node Properties |
590 | |
591 | // Generate class IDs for (some) ideal nodes so that it is possible to determine |
592 | // the type of a node using a non-virtual method call (the method is_<Node>() below). |
593 | // |
594 | // A class ID of an ideal node is a set of bits. In a class ID, a single bit determines |
595 | // the type of the node the ID represents; another subset of an ID's bits are reserved |
596 | // for the superclasses of the node represented by the ID. |
597 | // |
598 | // By design, if A is a supertype of B, A.is_B() returns true and B.is_A() |
599 | // returns false. A.is_A() returns true. |
600 | // |
601 | // If two classes, A and B, have the same superclass, a different bit of A's class id |
602 | // is reserved for A's type than for B's type. That bit is specified by the third |
603 | // parameter in the macro DEFINE_CLASS_ID. |
604 | // |
605 | // By convention, classes with deeper hierarchy are declared first. Moreover, |
606 | // classes with the same hierarchy depth are sorted by usage frequency. |
607 | // |
608 | // The query method masks the bits to cut off bits of subclasses and then compares |
609 | // the result with the class id (see the macro DEFINE_CLASS_QUERY below). |
610 | // |
611 | // Class_MachCall=30, ClassMask_MachCall=31 |
612 | // 12 8 4 0 |
613 | // 0 0 0 0 0 0 0 0 1 1 1 1 0 |
614 | // | | | | |
615 | // | | | Bit_Mach=2 |
616 | // | | Bit_MachReturn=4 |
617 | // | Bit_MachSafePoint=8 |
618 | // Bit_MachCall=16 |
619 | // |
620 | // Class_CountedLoop=56, ClassMask_CountedLoop=63 |
621 | // 12 8 4 0 |
622 | // 0 0 0 0 0 0 0 1 1 1 0 0 0 |
623 | // | | | |
624 | // | | Bit_Region=8 |
625 | // | Bit_Loop=16 |
626 | // Bit_CountedLoop=32 |
627 | |
628 | #define DEFINE_CLASS_ID(cl, supcl, subn) \ |
629 | Bit_##cl = (Class_##supcl == 0) ? 1 << subn : (Bit_##supcl) << (1 + subn) , \ |
630 | Class_##cl = Class_##supcl + Bit_##cl , \ |
631 | ClassMask_##cl = ((Bit_##cl << 1) - 1) , |
632 | |
633 | // This enum is used only for C2 ideal and mach nodes with is_<node>() methods |
634 | // so that its values fit into 32 bits. |
635 | enum NodeClasses { |
636 | Bit_Node = 0x00000000, |
637 | Class_Node = 0x00000000, |
638 | ClassMask_Node = 0xFFFFFFFF, |
639 | |
640 | DEFINE_CLASS_ID(Multi, Node, 0) |
641 | DEFINE_CLASS_ID(SafePoint, Multi, 0) |
642 | DEFINE_CLASS_ID(Call, SafePoint, 0) |
643 | DEFINE_CLASS_ID(CallJava, Call, 0) |
644 | DEFINE_CLASS_ID(CallStaticJava, CallJava, 0) |
645 | DEFINE_CLASS_ID(CallDynamicJava, CallJava, 1) |
646 | DEFINE_CLASS_ID(CallRuntime, Call, 1) |
647 | DEFINE_CLASS_ID(CallLeaf, CallRuntime, 0) |
648 | DEFINE_CLASS_ID(CallLeafNoFP, CallLeaf, 0) |
649 | DEFINE_CLASS_ID(Allocate, Call, 2) |
650 | DEFINE_CLASS_ID(AllocateArray, Allocate, 0) |
651 | DEFINE_CLASS_ID(AbstractLock, Call, 3) |
652 | DEFINE_CLASS_ID(Lock, AbstractLock, 0) |
653 | DEFINE_CLASS_ID(Unlock, AbstractLock, 1) |
654 | DEFINE_CLASS_ID(ArrayCopy, Call, 4) |
655 | DEFINE_CLASS_ID(CallNative, Call, 5) |
656 | DEFINE_CLASS_ID(MultiBranch, Multi, 1) |
657 | DEFINE_CLASS_ID(PCTable, MultiBranch, 0) |
658 | DEFINE_CLASS_ID(Catch, PCTable, 0) |
659 | DEFINE_CLASS_ID(Jump, PCTable, 1) |
660 | DEFINE_CLASS_ID(If, MultiBranch, 1) |
661 | DEFINE_CLASS_ID(BaseCountedLoopEnd, If, 0) |
662 | DEFINE_CLASS_ID(CountedLoopEnd, BaseCountedLoopEnd, 0) |
663 | DEFINE_CLASS_ID(LongCountedLoopEnd, BaseCountedLoopEnd, 1) |
664 | DEFINE_CLASS_ID(RangeCheck, If, 1) |
665 | DEFINE_CLASS_ID(OuterStripMinedLoopEnd, If, 2) |
666 | DEFINE_CLASS_ID(NeverBranch, MultiBranch, 2) |
667 | DEFINE_CLASS_ID(Start, Multi, 2) |
668 | DEFINE_CLASS_ID(MemBar, Multi, 3) |
669 | DEFINE_CLASS_ID(Initialize, MemBar, 0) |
670 | DEFINE_CLASS_ID(MemBarStoreStore, MemBar, 1) |
671 | |
672 | DEFINE_CLASS_ID(Mach, Node, 1) |
673 | DEFINE_CLASS_ID(MachReturn, Mach, 0) |
674 | DEFINE_CLASS_ID(MachSafePoint, MachReturn, 0) |
675 | DEFINE_CLASS_ID(MachCall, MachSafePoint, 0) |
676 | DEFINE_CLASS_ID(MachCallJava, MachCall, 0) |
677 | DEFINE_CLASS_ID(MachCallStaticJava, MachCallJava, 0) |
678 | DEFINE_CLASS_ID(MachCallDynamicJava, MachCallJava, 1) |
679 | DEFINE_CLASS_ID(MachCallRuntime, MachCall, 1) |
680 | DEFINE_CLASS_ID(MachCallLeaf, MachCallRuntime, 0) |
681 | DEFINE_CLASS_ID(MachCallNative, MachCall, 2) |
682 | DEFINE_CLASS_ID(MachBranch, Mach, 1) |
683 | DEFINE_CLASS_ID(MachIf, MachBranch, 0) |
684 | DEFINE_CLASS_ID(MachGoto, MachBranch, 1) |
685 | DEFINE_CLASS_ID(MachNullCheck, MachBranch, 2) |
686 | DEFINE_CLASS_ID(MachSpillCopy, Mach, 2) |
687 | DEFINE_CLASS_ID(MachTemp, Mach, 3) |
688 | DEFINE_CLASS_ID(MachConstantBase, Mach, 4) |
689 | DEFINE_CLASS_ID(MachConstant, Mach, 5) |
690 | DEFINE_CLASS_ID(MachJump, MachConstant, 0) |
691 | DEFINE_CLASS_ID(MachMerge, Mach, 6) |
692 | DEFINE_CLASS_ID(MachMemBar, Mach, 7) |
693 | |
694 | DEFINE_CLASS_ID(Type, Node, 2) |
695 | DEFINE_CLASS_ID(Phi, Type, 0) |
696 | DEFINE_CLASS_ID(ConstraintCast, Type, 1) |
697 | DEFINE_CLASS_ID(CastII, ConstraintCast, 0) |
698 | DEFINE_CLASS_ID(CheckCastPP, ConstraintCast, 1) |
699 | DEFINE_CLASS_ID(CastLL, ConstraintCast, 2) |
700 | DEFINE_CLASS_ID(CastFF, ConstraintCast, 3) |
701 | DEFINE_CLASS_ID(CastDD, ConstraintCast, 4) |
702 | DEFINE_CLASS_ID(CastVV, ConstraintCast, 5) |
703 | DEFINE_CLASS_ID(CMove, Type, 3) |
704 | DEFINE_CLASS_ID(SafePointScalarObject, Type, 4) |
705 | DEFINE_CLASS_ID(DecodeNarrowPtr, Type, 5) |
706 | DEFINE_CLASS_ID(DecodeN, DecodeNarrowPtr, 0) |
707 | DEFINE_CLASS_ID(DecodeNKlass, DecodeNarrowPtr, 1) |
708 | DEFINE_CLASS_ID(EncodeNarrowPtr, Type, 6) |
709 | DEFINE_CLASS_ID(EncodeP, EncodeNarrowPtr, 0) |
710 | DEFINE_CLASS_ID(EncodePKlass, EncodeNarrowPtr, 1) |
711 | DEFINE_CLASS_ID(Vector, Type, 7) |
712 | DEFINE_CLASS_ID(VectorMaskCmp, Vector, 0) |
713 | DEFINE_CLASS_ID(VectorUnbox, Vector, 1) |
714 | DEFINE_CLASS_ID(VectorReinterpret, Vector, 2) |
715 | DEFINE_CLASS_ID(ShiftV, Vector, 3) |
716 | |
717 | DEFINE_CLASS_ID(Proj, Node, 3) |
718 | DEFINE_CLASS_ID(CatchProj, Proj, 0) |
719 | DEFINE_CLASS_ID(JumpProj, Proj, 1) |
720 | DEFINE_CLASS_ID(IfProj, Proj, 2) |
721 | DEFINE_CLASS_ID(IfTrue, IfProj, 0) |
722 | DEFINE_CLASS_ID(IfFalse, IfProj, 1) |
723 | DEFINE_CLASS_ID(Parm, Proj, 4) |
724 | DEFINE_CLASS_ID(MachProj, Proj, 5) |
725 | |
726 | DEFINE_CLASS_ID(Mem, Node, 4) |
727 | DEFINE_CLASS_ID(Load, Mem, 0) |
728 | DEFINE_CLASS_ID(LoadVector, Load, 0) |
729 | DEFINE_CLASS_ID(LoadVectorGather, LoadVector, 0) |
730 | DEFINE_CLASS_ID(LoadVectorMasked, LoadVector, 1) |
731 | DEFINE_CLASS_ID(Store, Mem, 1) |
732 | DEFINE_CLASS_ID(StoreVector, Store, 0) |
733 | DEFINE_CLASS_ID(StoreVectorScatter, StoreVector, 0) |
734 | DEFINE_CLASS_ID(StoreVectorMasked, StoreVector, 1) |
735 | DEFINE_CLASS_ID(LoadStore, Mem, 2) |
736 | DEFINE_CLASS_ID(LoadStoreConditional, LoadStore, 0) |
737 | DEFINE_CLASS_ID(CompareAndSwap, LoadStoreConditional, 0) |
738 | DEFINE_CLASS_ID(CompareAndExchangeNode, LoadStore, 1) |
739 | |
740 | DEFINE_CLASS_ID(Region, Node, 5) |
741 | DEFINE_CLASS_ID(Loop, Region, 0) |
742 | DEFINE_CLASS_ID(Root, Loop, 0) |
743 | DEFINE_CLASS_ID(BaseCountedLoop, Loop, 1) |
744 | DEFINE_CLASS_ID(CountedLoop, BaseCountedLoop, 0) |
745 | DEFINE_CLASS_ID(LongCountedLoop, BaseCountedLoop, 1) |
746 | DEFINE_CLASS_ID(OuterStripMinedLoop, Loop, 2) |
747 | |
748 | DEFINE_CLASS_ID(Sub, Node, 6) |
749 | DEFINE_CLASS_ID(Cmp, Sub, 0) |
750 | DEFINE_CLASS_ID(FastLock, Cmp, 0) |
751 | DEFINE_CLASS_ID(FastUnlock, Cmp, 1) |
752 | DEFINE_CLASS_ID(SubTypeCheck,Cmp, 2) |
753 | |
754 | DEFINE_CLASS_ID(MergeMem, Node, 7) |
755 | DEFINE_CLASS_ID(Bool, Node, 8) |
756 | DEFINE_CLASS_ID(AddP, Node, 9) |
757 | DEFINE_CLASS_ID(BoxLock, Node, 10) |
758 | DEFINE_CLASS_ID(Add, Node, 11) |
759 | DEFINE_CLASS_ID(Mul, Node, 12) |
760 | DEFINE_CLASS_ID(ClearArray, Node, 14) |
761 | DEFINE_CLASS_ID(Halt, Node, 15) |
762 | DEFINE_CLASS_ID(Opaque1, Node, 16) |
763 | DEFINE_CLASS_ID(Move, Node, 17) |
764 | DEFINE_CLASS_ID(LShift, Node, 18) |
765 | |
766 | _max_classes = ClassMask_Move |
767 | }; |
768 | #undef DEFINE_CLASS_ID |
769 | |
770 | // Flags are sorted by usage frequency. |
771 | enum NodeFlags { |
772 | Flag_is_Copy = 1 << 0, // should be first bit to avoid shift |
773 | Flag_rematerialize = 1 << 1, |
774 | Flag_needs_anti_dependence_check = 1 << 2, |
775 | Flag_is_macro = 1 << 3, |
776 | Flag_is_Con = 1 << 4, |
777 | Flag_is_cisc_alternate = 1 << 5, |
778 | Flag_is_dead_loop_safe = 1 << 6, |
779 | Flag_may_be_short_branch = 1 << 7, |
780 | Flag_avoid_back_to_back_before = 1 << 8, |
781 | Flag_avoid_back_to_back_after = 1 << 9, |
782 | Flag_has_call = 1 << 10, |
783 | Flag_is_reduction = 1 << 11, |
784 | Flag_is_scheduled = 1 << 12, |
785 | Flag_has_vector_mask_set = 1 << 13, |
786 | Flag_is_expensive = 1 << 14, |
787 | Flag_is_predicated_vector = 1 << 15, |
788 | Flag_for_post_loop_opts_igvn = 1 << 16, |
789 | _last_flag = Flag_for_post_loop_opts_igvn |
790 | }; |
791 | |
792 | class PD; |
793 | |
794 | private: |
795 | juint _class_id; |
796 | juint _flags; |
797 | |
798 | static juint max_flags(); |
799 | |
800 | protected: |
801 | // These methods should be called from constructors only. |
802 | void init_class_id(juint c) { |
803 | _class_id = c; // cast out const |
804 | } |
805 | void init_flags(uint fl) { |
806 | assert(fl <= max_flags(), "invalid node flag")do { if (!(fl <= max_flags())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 806, "assert(" "fl <= max_flags()" ") failed", "invalid node flag" ); ::breakpoint(); } } while (0); |
807 | _flags |= fl; |
808 | } |
809 | void clear_flag(uint fl) { |
810 | assert(fl <= max_flags(), "invalid node flag")do { if (!(fl <= max_flags())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 810, "assert(" "fl <= max_flags()" ") failed", "invalid node flag" ); ::breakpoint(); } } while (0); |
811 | _flags &= ~fl; |
812 | } |
813 | |
814 | public: |
815 | const juint class_id() const { return _class_id; } |
816 | |
817 | const juint flags() const { return _flags; } |
818 | |
819 | void add_flag(juint fl) { init_flags(fl); } |
820 | |
821 | void remove_flag(juint fl) { clear_flag(fl); } |
822 | |
823 | // Return a dense integer opcode number |
824 | virtual int Opcode() const; |
825 | |
826 | // Virtual inherited Node size |
827 | virtual uint size_of() const; |
828 | |
829 | // Other interesting Node properties |
830 | #define DEFINE_CLASS_QUERY(type) \ |
831 | bool is_##type() const { \ |
832 | return ((_class_id & ClassMask_##type) == Class_##type); \ |
833 | } \ |
834 | type##Node *as_##type() const { \ |
835 | assert(is_##type(), "invalid node class: %s", Name())do { if (!(is_##type())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 835, "assert(" "is_##type()" ") failed", "invalid node class: %s" , Name()); ::breakpoint(); } } while (0); \ |
836 | return (type##Node*)this; \ |
837 | } \ |
838 | type##Node* isa_##type() const { \ |
839 | return (is_##type()) ? as_##type() : NULL__null; \ |
840 | } |
841 | |
842 | DEFINE_CLASS_QUERY(AbstractLock) |
843 | DEFINE_CLASS_QUERY(Add) |
844 | DEFINE_CLASS_QUERY(AddP) |
845 | DEFINE_CLASS_QUERY(Allocate) |
846 | DEFINE_CLASS_QUERY(AllocateArray) |
847 | DEFINE_CLASS_QUERY(ArrayCopy) |
848 | DEFINE_CLASS_QUERY(BaseCountedLoop) |
849 | DEFINE_CLASS_QUERY(BaseCountedLoopEnd) |
850 | DEFINE_CLASS_QUERY(Bool) |
851 | DEFINE_CLASS_QUERY(BoxLock) |
852 | DEFINE_CLASS_QUERY(Call) |
853 | DEFINE_CLASS_QUERY(CallNative) |
854 | DEFINE_CLASS_QUERY(CallDynamicJava) |
855 | DEFINE_CLASS_QUERY(CallJava) |
856 | DEFINE_CLASS_QUERY(CallLeaf) |
857 | DEFINE_CLASS_QUERY(CallLeafNoFP) |
858 | DEFINE_CLASS_QUERY(CallRuntime) |
859 | DEFINE_CLASS_QUERY(CallStaticJava) |
860 | DEFINE_CLASS_QUERY(Catch) |
861 | DEFINE_CLASS_QUERY(CatchProj) |
862 | DEFINE_CLASS_QUERY(CheckCastPP) |
863 | DEFINE_CLASS_QUERY(CastII) |
864 | DEFINE_CLASS_QUERY(CastLL) |
865 | DEFINE_CLASS_QUERY(ConstraintCast) |
866 | DEFINE_CLASS_QUERY(ClearArray) |
867 | DEFINE_CLASS_QUERY(CMove) |
868 | DEFINE_CLASS_QUERY(Cmp) |
869 | DEFINE_CLASS_QUERY(CountedLoop) |
870 | DEFINE_CLASS_QUERY(CountedLoopEnd) |
871 | DEFINE_CLASS_QUERY(DecodeNarrowPtr) |
872 | DEFINE_CLASS_QUERY(DecodeN) |
873 | DEFINE_CLASS_QUERY(DecodeNKlass) |
874 | DEFINE_CLASS_QUERY(EncodeNarrowPtr) |
875 | DEFINE_CLASS_QUERY(EncodeP) |
876 | DEFINE_CLASS_QUERY(EncodePKlass) |
877 | DEFINE_CLASS_QUERY(FastLock) |
878 | DEFINE_CLASS_QUERY(FastUnlock) |
879 | DEFINE_CLASS_QUERY(Halt) |
880 | DEFINE_CLASS_QUERY(If) |
881 | DEFINE_CLASS_QUERY(RangeCheck) |
882 | DEFINE_CLASS_QUERY(IfProj) |
883 | DEFINE_CLASS_QUERY(IfFalse) |
884 | DEFINE_CLASS_QUERY(IfTrue) |
885 | DEFINE_CLASS_QUERY(Initialize) |
886 | DEFINE_CLASS_QUERY(Jump) |
887 | DEFINE_CLASS_QUERY(JumpProj) |
888 | DEFINE_CLASS_QUERY(LongCountedLoop) |
889 | DEFINE_CLASS_QUERY(LongCountedLoopEnd) |
890 | DEFINE_CLASS_QUERY(Load) |
891 | DEFINE_CLASS_QUERY(LoadStore) |
892 | DEFINE_CLASS_QUERY(LoadStoreConditional) |
893 | DEFINE_CLASS_QUERY(Lock) |
894 | DEFINE_CLASS_QUERY(Loop) |
895 | DEFINE_CLASS_QUERY(LShift) |
896 | DEFINE_CLASS_QUERY(Mach) |
897 | DEFINE_CLASS_QUERY(MachBranch) |
898 | DEFINE_CLASS_QUERY(MachCall) |
899 | DEFINE_CLASS_QUERY(MachCallNative) |
900 | DEFINE_CLASS_QUERY(MachCallDynamicJava) |
901 | DEFINE_CLASS_QUERY(MachCallJava) |
902 | DEFINE_CLASS_QUERY(MachCallLeaf) |
903 | DEFINE_CLASS_QUERY(MachCallRuntime) |
904 | DEFINE_CLASS_QUERY(MachCallStaticJava) |
905 | DEFINE_CLASS_QUERY(MachConstantBase) |
906 | DEFINE_CLASS_QUERY(MachConstant) |
907 | DEFINE_CLASS_QUERY(MachGoto) |
908 | DEFINE_CLASS_QUERY(MachIf) |
909 | DEFINE_CLASS_QUERY(MachJump) |
910 | DEFINE_CLASS_QUERY(MachNullCheck) |
911 | DEFINE_CLASS_QUERY(MachProj) |
912 | DEFINE_CLASS_QUERY(MachReturn) |
913 | DEFINE_CLASS_QUERY(MachSafePoint) |
914 | DEFINE_CLASS_QUERY(MachSpillCopy) |
915 | DEFINE_CLASS_QUERY(MachTemp) |
916 | DEFINE_CLASS_QUERY(MachMemBar) |
917 | DEFINE_CLASS_QUERY(MachMerge) |
918 | DEFINE_CLASS_QUERY(Mem) |
919 | DEFINE_CLASS_QUERY(MemBar) |
920 | DEFINE_CLASS_QUERY(MemBarStoreStore) |
921 | DEFINE_CLASS_QUERY(MergeMem) |
922 | DEFINE_CLASS_QUERY(Move) |
923 | DEFINE_CLASS_QUERY(Mul) |
924 | DEFINE_CLASS_QUERY(Multi) |
925 | DEFINE_CLASS_QUERY(MultiBranch) |
926 | DEFINE_CLASS_QUERY(Opaque1) |
927 | DEFINE_CLASS_QUERY(OuterStripMinedLoop) |
928 | DEFINE_CLASS_QUERY(OuterStripMinedLoopEnd) |
929 | DEFINE_CLASS_QUERY(Parm) |
930 | DEFINE_CLASS_QUERY(PCTable) |
931 | DEFINE_CLASS_QUERY(Phi) |
932 | DEFINE_CLASS_QUERY(Proj) |
933 | DEFINE_CLASS_QUERY(Region) |
934 | DEFINE_CLASS_QUERY(Root) |
935 | DEFINE_CLASS_QUERY(SafePoint) |
936 | DEFINE_CLASS_QUERY(SafePointScalarObject) |
937 | DEFINE_CLASS_QUERY(Start) |
938 | DEFINE_CLASS_QUERY(Store) |
939 | DEFINE_CLASS_QUERY(Sub) |
940 | DEFINE_CLASS_QUERY(SubTypeCheck) |
941 | DEFINE_CLASS_QUERY(Type) |
942 | DEFINE_CLASS_QUERY(Vector) |
943 | DEFINE_CLASS_QUERY(VectorMaskCmp) |
944 | DEFINE_CLASS_QUERY(VectorUnbox) |
945 | DEFINE_CLASS_QUERY(VectorReinterpret); |
946 | DEFINE_CLASS_QUERY(LoadVector) |
947 | DEFINE_CLASS_QUERY(LoadVectorGather) |
948 | DEFINE_CLASS_QUERY(StoreVector) |
949 | DEFINE_CLASS_QUERY(StoreVectorScatter) |
950 | DEFINE_CLASS_QUERY(ShiftV) |
951 | DEFINE_CLASS_QUERY(Unlock) |
952 | |
953 | #undef DEFINE_CLASS_QUERY |
954 | |
955 | // duplicate of is_MachSpillCopy() |
956 | bool is_SpillCopy () const { |
957 | return ((_class_id & ClassMask_MachSpillCopy) == Class_MachSpillCopy); |
958 | } |
959 | |
960 | bool is_Con () const { return (_flags & Flag_is_Con) != 0; } |
961 | // The data node which is safe to leave in dead loop during IGVN optimization. |
962 | bool is_dead_loop_safe() const; |
963 | |
964 | // is_Copy() returns copied edge index (0 or 1) |
965 | uint is_Copy() const { return (_flags & Flag_is_Copy); } |
966 | |
967 | virtual bool is_CFG() const { return false; } |
968 | |
969 | // If this node is control-dependent on a test, can it be |
970 | // rerouted to a dominating equivalent test? This is usually |
971 | // true of non-CFG nodes, but can be false for operations which |
972 | // depend for their correct sequencing on more than one test. |
973 | // (In that case, hoisting to a dominating test may silently |
974 | // skip some other important test.) |
975 | virtual bool depends_only_on_test() const { assert(!is_CFG(), "")do { if (!(!is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 975, "assert(" "!is_CFG()" ") failed", ""); ::breakpoint(); } } while (0); return true; }; |
976 | |
977 | // When building basic blocks, I need to have a notion of block beginning |
978 | // Nodes, next block selector Nodes (block enders), and next block |
979 | // projections. These calls need to work on their machine equivalents. The |
980 | // Ideal beginning Nodes are RootNode, RegionNode and StartNode. |
981 | bool is_block_start() const { |
982 | if ( is_Region() ) |
983 | return this == (const Node*)in(0); |
984 | else |
985 | return is_Start(); |
986 | } |
987 | |
988 | // The Ideal control projection Nodes are IfTrue/IfFalse, JumpProjNode, Root, |
989 | // Goto and Return. This call also returns the block ending Node. |
990 | virtual const Node *is_block_proj() const; |
991 | |
992 | // The node is a "macro" node which needs to be expanded before matching |
993 | bool is_macro() const { return (_flags & Flag_is_macro) != 0; } |
994 | // The node is expensive: the best control is set during loop opts |
995 | bool is_expensive() const { return (_flags & Flag_is_expensive) != 0 && in(0) != NULL__null; } |
996 | |
997 | // An arithmetic node which accumulates a data in a loop. |
998 | // It must have the loop's phi as input and provide a def to the phi. |
999 | bool is_reduction() const { return (_flags & Flag_is_reduction) != 0; } |
1000 | |
1001 | bool is_predicated_vector() const { return (_flags & Flag_is_predicated_vector) != 0; } |
1002 | |
1003 | // The node is a CountedLoopEnd with a mask annotation so as to emit a restore context |
1004 | bool has_vector_mask_set() const { return (_flags & Flag_has_vector_mask_set) != 0; } |
1005 | |
1006 | // Used in lcm to mark nodes that have scheduled |
1007 | bool is_scheduled() const { return (_flags & Flag_is_scheduled) != 0; } |
1008 | |
1009 | bool for_post_loop_opts_igvn() const { return (_flags & Flag_for_post_loop_opts_igvn) != 0; } |
1010 | |
1011 | //----------------- Optimization |
1012 | |
1013 | // Get the worst-case Type output for this Node. |
1014 | virtual const class Type *bottom_type() const; |
1015 | |
1016 | // If we find a better type for a node, try to record it permanently. |
1017 | // Return true if this node actually changed. |
1018 | // Be sure to do the hash_delete game in the "rehash" variant. |
1019 | void raise_bottom_type(const Type* new_type); |
1020 | |
1021 | // Get the address type with which this node uses and/or defs memory, |
1022 | // or NULL if none. The address type is conservatively wide. |
1023 | // Returns non-null for calls, membars, loads, stores, etc. |
1024 | // Returns TypePtr::BOTTOM if the node touches memory "broadly". |
1025 | virtual const class TypePtr *adr_type() const { return NULL__null; } |
1026 | |
1027 | // Return an existing node which computes the same function as this node. |
1028 | // The optimistic combined algorithm requires this to return a Node which |
1029 | // is a small number of steps away (e.g., one of my inputs). |
1030 | virtual Node* Identity(PhaseGVN* phase); |
1031 | |
1032 | // Return the set of values this Node can take on at runtime. |
1033 | virtual const Type* Value(PhaseGVN* phase) const; |
1034 | |
1035 | // Return a node which is more "ideal" than the current node. |
1036 | // The invariants on this call are subtle. If in doubt, read the |
1037 | // treatise in node.cpp above the default implemention AND TEST WITH |
1038 | // +VerifyIterativeGVN! |
1039 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); |
1040 | |
1041 | // Some nodes have specific Ideal subgraph transformations only if they are |
1042 | // unique users of specific nodes. Such nodes should be put on IGVN worklist |
1043 | // for the transformations to happen. |
1044 | bool has_special_unique_user() const; |
1045 | |
1046 | // Skip Proj and CatchProj nodes chains. Check for Null and Top. |
1047 | Node* find_exact_control(Node* ctrl); |
1048 | |
1049 | // Check if 'this' node dominates or equal to 'sub'. |
1050 | bool dominates(Node* sub, Node_List &nlist); |
1051 | |
1052 | protected: |
1053 | bool remove_dead_region(PhaseGVN *phase, bool can_reshape); |
1054 | public: |
1055 | |
1056 | // See if there is valid pipeline info |
1057 | static const Pipeline *pipeline_class(); |
1058 | virtual const Pipeline *pipeline() const; |
1059 | |
1060 | // Compute the latency from the def to this instruction of the ith input node |
1061 | uint latency(uint i); |
1062 | |
1063 | // Hash & compare functions, for pessimistic value numbering |
1064 | |
1065 | // If the hash function returns the special sentinel value NO_HASH, |
1066 | // the node is guaranteed never to compare equal to any other node. |
1067 | // If we accidentally generate a hash with value NO_HASH the node |
1068 | // won't go into the table and we'll lose a little optimization. |
1069 | static const uint NO_HASH = 0; |
1070 | virtual uint hash() const; |
1071 | virtual bool cmp( const Node &n ) const; |
1072 | |
1073 | // Operation appears to be iteratively computed (such as an induction variable) |
1074 | // It is possible for this operation to return false for a loop-varying |
1075 | // value, if it appears (by local graph inspection) to be computed by a simple conditional. |
1076 | bool is_iteratively_computed(); |
1077 | |
1078 | // Determine if a node is a counted loop induction variable. |
1079 | // NOTE: The method is defined in "loopnode.cpp". |
1080 | bool is_cloop_ind_var() const; |
1081 | |
1082 | // Return a node with opcode "opc" and same inputs as "this" if one can |
1083 | // be found; Otherwise return NULL; |
1084 | Node* find_similar(int opc); |
1085 | |
1086 | // Return the unique control out if only one. Null if none or more than one. |
1087 | Node* unique_ctrl_out() const; |
1088 | |
1089 | // Set control or add control as precedence edge |
1090 | void ensure_control_or_add_prec(Node* c); |
1091 | |
1092 | //----------------- Code Generation |
1093 | |
1094 | // Ideal register class for Matching. Zero means unmatched instruction |
1095 | // (these are cloned instead of converted to machine nodes). |
1096 | virtual uint ideal_reg() const; |
1097 | |
1098 | static const uint NotAMachineReg; // must be > max. machine register |
1099 | |
1100 | // Do we Match on this edge index or not? Generally false for Control |
1101 | // and true for everything else. Weird for calls & returns. |
1102 | virtual uint match_edge(uint idx) const; |
1103 | |
1104 | // Register class output is returned in |
1105 | virtual const RegMask &out_RegMask() const; |
1106 | // Register class input is expected in |
1107 | virtual const RegMask &in_RegMask(uint) const; |
1108 | // Should we clone rather than spill this instruction? |
1109 | bool rematerialize() const; |
1110 | |
1111 | // Return JVM State Object if this Node carries debug info, or NULL otherwise |
1112 | virtual JVMState* jvms() const; |
1113 | |
1114 | // Print as assembly |
1115 | virtual void format( PhaseRegAlloc *, outputStream* st = tty ) const; |
1116 | // Emit bytes starting at parameter 'ptr' |
1117 | // Bump 'ptr' by the number of output bytes |
1118 | virtual void emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const; |
1119 | // Size of instruction in bytes |
1120 | virtual uint size(PhaseRegAlloc *ra_) const; |
1121 | |
1122 | // Convenience function to extract an integer constant from a node. |
1123 | // If it is not an integer constant (either Con, CastII, or Mach), |
1124 | // return value_if_unknown. |
1125 | jint find_int_con(jint value_if_unknown) const { |
1126 | const TypeInt* t = find_int_type(); |
1127 | return (t != NULL__null && t->is_con()) ? t->get_con() : value_if_unknown; |
1128 | } |
1129 | // Return the constant, knowing it is an integer constant already |
1130 | jint get_int() const { |
1131 | const TypeInt* t = find_int_type(); |
1132 | guarantee(t != NULL, "must be con")do { if (!(t != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1132, "guarantee(" "t != NULL" ") failed", "must be con"); :: breakpoint(); } } while (0); |
1133 | return t->get_con(); |
1134 | } |
1135 | // Here's where the work is done. Can produce non-constant int types too. |
1136 | const TypeInt* find_int_type() const; |
1137 | const TypeInteger* find_integer_type(BasicType bt) const; |
1138 | |
1139 | // Same thing for long (and intptr_t, via type.hpp): |
1140 | jlong get_long() const { |
1141 | const TypeLong* t = find_long_type(); |
1142 | guarantee(t != NULL, "must be con")do { if (!(t != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1142, "guarantee(" "t != NULL" ") failed", "must be con"); :: breakpoint(); } } while (0); |
1143 | return t->get_con(); |
1144 | } |
1145 | jlong find_long_con(jint value_if_unknown) const { |
1146 | const TypeLong* t = find_long_type(); |
1147 | return (t != NULL__null && t->is_con()) ? t->get_con() : value_if_unknown; |
1148 | } |
1149 | const TypeLong* find_long_type() const; |
1150 | |
1151 | jlong get_integer_as_long(BasicType bt) const { |
1152 | const TypeInteger* t = find_integer_type(bt); |
1153 | guarantee(t != NULL, "must be con")do { if (!(t != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1153, "guarantee(" "t != NULL" ") failed", "must be con"); :: breakpoint(); } } while (0); |
1154 | return t->get_con_as_long(bt); |
1155 | } |
1156 | const TypePtr* get_ptr_type() const; |
1157 | |
1158 | // These guys are called by code generated by ADLC: |
1159 | intptr_t get_ptr() const; |
1160 | intptr_t get_narrowcon() const; |
1161 | jdouble getd() const; |
1162 | jfloat getf() const; |
1163 | |
1164 | // Nodes which are pinned into basic blocks |
1165 | virtual bool pinned() const { return false; } |
1166 | |
1167 | // Nodes which use memory without consuming it, hence need antidependences |
1168 | // More specifically, needs_anti_dependence_check returns true iff the node |
1169 | // (a) does a load, and (b) does not perform a store (except perhaps to a |
1170 | // stack slot or some other unaliased location). |
1171 | bool needs_anti_dependence_check() const; |
1172 | |
1173 | // Return which operand this instruction may cisc-spill. In other words, |
1174 | // return operand position that can convert from reg to memory access |
1175 | virtual int cisc_operand() const { return AdlcVMDeps::Not_cisc_spillable; } |
1176 | bool is_cisc_alternate() const { return (_flags & Flag_is_cisc_alternate) != 0; } |
1177 | |
1178 | // Whether this is a memory-writing machine node. |
1179 | bool is_memory_writer() const { return is_Mach() && bottom_type()->has_memory(); } |
1180 | |
1181 | //----------------- Printing, etc |
1182 | #ifndef PRODUCT |
1183 | private: |
1184 | int _indent; |
1185 | |
1186 | public: |
1187 | void set_indent(int indent) { _indent = indent; } |
1188 | |
1189 | private: |
1190 | static bool add_to_worklist(Node* n, Node_List* worklist, Arena* old_arena, VectorSet* old_space, VectorSet* new_space); |
1191 | public: |
1192 | Node* find(int idx, bool only_ctrl = false); // Search the graph for the given idx. |
1193 | Node* find_ctrl(int idx); // Search control ancestors for the given idx. |
1194 | void dump() const { dump("\n"); } // Print this node. |
1195 | void dump(const char* suffix, bool mark = false, outputStream *st = tty) const; // Print this node. |
1196 | void dump(int depth) const; // Print this node, recursively to depth d |
1197 | void dump_ctrl(int depth) const; // Print control nodes, to depth d |
1198 | void dump_comp() const; // Print this node in compact representation. |
1199 | // Print this node in compact representation. |
1200 | void dump_comp(const char* suffix, outputStream *st = tty) const; |
1201 | virtual void dump_req(outputStream *st = tty) const; // Print required-edge info |
1202 | virtual void dump_prec(outputStream *st = tty) const; // Print precedence-edge info |
1203 | virtual void dump_out(outputStream *st = tty) const; // Print the output edge info |
1204 | virtual void dump_spec(outputStream *st) const {}; // Print per-node info |
1205 | // Print compact per-node info |
1206 | virtual void dump_compact_spec(outputStream *st) const { dump_spec(st); } |
1207 | void dump_related() const; // Print related nodes (depends on node at hand). |
1208 | // Print related nodes up to given depths for input and output nodes. |
1209 | void dump_related(uint d_in, uint d_out) const; |
1210 | void dump_related_compact() const; // Print related nodes in compact representation. |
1211 | // Collect related nodes. |
1212 | virtual void related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_rel, bool compact) const; |
1213 | // Collect nodes starting from this node, explicitly including/excluding control and data links. |
1214 | void collect_nodes(GrowableArray<Node*> *ns, int d, bool ctrl, bool data) const; |
1215 | |
1216 | // Node collectors, to be used in implementations of Node::rel(). |
1217 | // Collect the entire data input graph. Include control inputs if requested. |
1218 | void collect_nodes_in_all_data(GrowableArray<Node*> *ns, bool ctrl) const; |
1219 | // Collect the entire control input graph. Include data inputs if requested. |
1220 | void collect_nodes_in_all_ctrl(GrowableArray<Node*> *ns, bool data) const; |
1221 | // Collect the entire output graph until hitting and including control nodes. |
1222 | void collect_nodes_out_all_ctrl_boundary(GrowableArray<Node*> *ns) const; |
1223 | |
1224 | void verify_edges(Unique_Node_List &visited); // Verify bi-directional edges |
1225 | static void verify(int verify_depth, VectorSet& visited, Node_List& worklist); |
1226 | |
1227 | // This call defines a class-unique string used to identify class instances |
1228 | virtual const char *Name() const; |
1229 | |
1230 | void dump_format(PhaseRegAlloc *ra) const; // debug access to MachNode::format(...) |
1231 | // RegMask Print Functions |
1232 | void dump_in_regmask(int idx) { in_RegMask(idx).dump(); } |
1233 | void dump_out_regmask() { out_RegMask().dump(); } |
1234 | static bool in_dump() { return Compile::current()->_in_dump_cnt > 0; } |
1235 | void fast_dump() const { |
1236 | tty->print("%4d: %-17s", _idx, Name()); |
1237 | for (uint i = 0; i < len(); i++) |
1238 | if (in(i)) |
1239 | tty->print(" %4d", in(i)->_idx); |
1240 | else |
1241 | tty->print(" NULL"); |
1242 | tty->print("\n"); |
1243 | } |
1244 | #endif |
1245 | #ifdef ASSERT1 |
1246 | void verify_construction(); |
1247 | bool verify_jvms(const JVMState* jvms) const; |
1248 | int _debug_idx; // Unique value assigned to every node. |
1249 | int debug_idx() const { return _debug_idx; } |
1250 | void set_debug_idx( int debug_idx ) { _debug_idx = debug_idx; } |
1251 | |
1252 | Node* _debug_orig; // Original version of this, if any. |
1253 | Node* debug_orig() const { return _debug_orig; } |
1254 | void set_debug_orig(Node* orig); // _debug_orig = orig |
1255 | void dump_orig(outputStream *st, bool print_key = true) const; |
1256 | |
1257 | int _hash_lock; // Barrier to modifications of nodes in the hash table |
1258 | void enter_hash_lock() { ++_hash_lock; assert(_hash_lock < 99, "in too many hash tables?")do { if (!(_hash_lock < 99)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1258, "assert(" "_hash_lock < 99" ") failed", "in too many hash tables?" ); ::breakpoint(); } } while (0); } |
1259 | void exit_hash_lock() { --_hash_lock; assert(_hash_lock >= 0, "mispaired hash locks")do { if (!(_hash_lock >= 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1259, "assert(" "_hash_lock >= 0" ") failed", "mispaired hash locks" ); ::breakpoint(); } } while (0); } |
1260 | |
1261 | static void init_NodeProperty(); |
1262 | |
1263 | #if OPTO_DU_ITERATOR_ASSERT1 |
1264 | const Node* _last_del; // The last deleted node. |
1265 | uint _del_tick; // Bumped when a deletion happens.. |
1266 | #endif |
1267 | #endif |
1268 | }; |
1269 | |
1270 | inline bool not_a_node(const Node* n) { |
1271 | if (n == NULL__null) return true; |
1272 | if (((intptr_t)n & 1) != 0) return true; // uninitialized, etc. |
1273 | if (*(address*)n == badAddress((address)::badAddressVal)) return true; // kill by Node::destruct |
1274 | return false; |
1275 | } |
1276 | |
1277 | //----------------------------------------------------------------------------- |
1278 | // Iterators over DU info, and associated Node functions. |
1279 | |
1280 | #if OPTO_DU_ITERATOR_ASSERT1 |
1281 | |
1282 | // Common code for assertion checking on DU iterators. |
1283 | class DUIterator_Common { |
1284 | #ifdef ASSERT1 |
1285 | protected: |
1286 | bool _vdui; // cached value of VerifyDUIterators |
1287 | const Node* _node; // the node containing the _out array |
1288 | uint _outcnt; // cached node->_outcnt |
1289 | uint _del_tick; // cached node->_del_tick |
1290 | Node* _last; // last value produced by the iterator |
1291 | |
1292 | void sample(const Node* node); // used by c'tor to set up for verifies |
1293 | void verify(const Node* node, bool at_end_ok = false); |
1294 | void verify_resync(); |
1295 | void reset(const DUIterator_Common& that); |
1296 | |
1297 | // The VDUI_ONLY macro protects code conditionalized on VerifyDUIterators |
1298 | #define I_VDUI_ONLY(i,x) { if ((i)._vdui) { x; } } |
1299 | #else |
1300 | #define I_VDUI_ONLY(i,x) { } |
1301 | #endif //ASSERT |
1302 | }; |
1303 | |
1304 | #define VDUI_ONLY(x) I_VDUI_ONLY(*this, x) |
1305 | |
1306 | // Default DU iterator. Allows appends onto the out array. |
1307 | // Allows deletion from the out array only at the current point. |
1308 | // Usage: |
1309 | // for (DUIterator i = x->outs(); x->has_out(i); i++) { |
1310 | // Node* y = x->out(i); |
1311 | // ... |
1312 | // } |
1313 | // Compiles in product mode to a unsigned integer index, which indexes |
1314 | // onto a repeatedly reloaded base pointer of x->_out. The loop predicate |
1315 | // also reloads x->_outcnt. If you delete, you must perform "--i" just |
1316 | // before continuing the loop. You must delete only the last-produced |
1317 | // edge. You must delete only a single copy of the last-produced edge, |
1318 | // or else you must delete all copies at once (the first time the edge |
1319 | // is produced by the iterator). |
1320 | class DUIterator : public DUIterator_Common { |
1321 | friend class Node; |
1322 | |
1323 | // This is the index which provides the product-mode behavior. |
1324 | // Whatever the product-mode version of the system does to the |
1325 | // DUI index is done to this index. All other fields in |
1326 | // this class are used only for assertion checking. |
1327 | uint _idx; |
1328 | |
1329 | #ifdef ASSERT1 |
1330 | uint _refresh_tick; // Records the refresh activity. |
1331 | |
1332 | void sample(const Node* node); // Initialize _refresh_tick etc. |
1333 | void verify(const Node* node, bool at_end_ok = false); |
1334 | void verify_increment(); // Verify an increment operation. |
1335 | void verify_resync(); // Verify that we can back up over a deletion. |
1336 | void verify_finish(); // Verify that the loop terminated properly. |
1337 | void refresh(); // Resample verification info. |
1338 | void reset(const DUIterator& that); // Resample after assignment. |
1339 | #endif |
1340 | |
1341 | DUIterator(const Node* node, int dummy_to_avoid_conversion) |
1342 | { _idx = 0; debug_only(sample(node))sample(node); } |
1343 | |
1344 | public: |
1345 | // initialize to garbage; clear _vdui to disable asserts |
1346 | DUIterator() |
1347 | { /*initialize to garbage*/ debug_only(_vdui = false)_vdui = false; } |
1348 | |
1349 | DUIterator(const DUIterator& that) |
1350 | { _idx = that._idx; debug_only(_vdui = false; reset(that))_vdui = false; reset(that); } |
1351 | |
1352 | void operator++(int dummy_to_specify_postfix_op) |
1353 | { _idx++; VDUI_ONLY(verify_increment()); } |
1354 | |
1355 | void operator--() |
1356 | { VDUI_ONLY(verify_resync()); --_idx; } |
1357 | |
1358 | ~DUIterator() |
1359 | { VDUI_ONLY(verify_finish()); } |
1360 | |
1361 | void operator=(const DUIterator& that) |
1362 | { _idx = that._idx; debug_only(reset(that))reset(that); } |
1363 | }; |
1364 | |
1365 | DUIterator Node::outs() const |
1366 | { return DUIterator(this, 0); } |
1367 | DUIterator& Node::refresh_out_pos(DUIterator& i) const |
1368 | { I_VDUI_ONLY(i, i.refresh()); return i; } |
1369 | bool Node::has_out(DUIterator& i) const |
1370 | { I_VDUI_ONLY(i, i.verify(this,true));return i._idx < _outcnt; } |
1371 | Node* Node::out(DUIterator& i) const |
1372 | { I_VDUI_ONLY(i, i.verify(this)); return debug_only(i._last=)i._last= _out[i._idx]; } |
1373 | |
1374 | |
1375 | // Faster DU iterator. Disallows insertions into the out array. |
1376 | // Allows deletion from the out array only at the current point. |
1377 | // Usage: |
1378 | // for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) { |
1379 | // Node* y = x->fast_out(i); |
1380 | // ... |
1381 | // } |
1382 | // Compiles in product mode to raw Node** pointer arithmetic, with |
1383 | // no reloading of pointers from the original node x. If you delete, |
1384 | // you must perform "--i; --imax" just before continuing the loop. |
1385 | // If you delete multiple copies of the same edge, you must decrement |
1386 | // imax, but not i, multiple times: "--i, imax -= num_edges". |
1387 | class DUIterator_Fast : public DUIterator_Common { |
1388 | friend class Node; |
1389 | friend class DUIterator_Last; |
1390 | |
1391 | // This is the pointer which provides the product-mode behavior. |
1392 | // Whatever the product-mode version of the system does to the |
1393 | // DUI pointer is done to this pointer. All other fields in |
1394 | // this class are used only for assertion checking. |
1395 | Node** _outp; |
1396 | |
1397 | #ifdef ASSERT1 |
1398 | void verify(const Node* node, bool at_end_ok = false); |
1399 | void verify_limit(); |
1400 | void verify_resync(); |
1401 | void verify_relimit(uint n); |
1402 | void reset(const DUIterator_Fast& that); |
1403 | #endif |
1404 | |
1405 | // Note: offset must be signed, since -1 is sometimes passed |
1406 | DUIterator_Fast(const Node* node, ptrdiff_t offset) |
1407 | { _outp = node->_out + offset; debug_only(sample(node))sample(node); } |
1408 | |
1409 | public: |
1410 | // initialize to garbage; clear _vdui to disable asserts |
1411 | DUIterator_Fast() |
1412 | { /*initialize to garbage*/ debug_only(_vdui = false)_vdui = false; } |
1413 | |
1414 | DUIterator_Fast(const DUIterator_Fast& that) |
1415 | { _outp = that._outp; debug_only(_vdui = false; reset(that))_vdui = false; reset(that); } |
1416 | |
1417 | void operator++(int dummy_to_specify_postfix_op) |
1418 | { _outp++; VDUI_ONLY(verify(_node, true)); } |
1419 | |
1420 | void operator--() |
1421 | { VDUI_ONLY(verify_resync()); --_outp; } |
1422 | |
1423 | void operator-=(uint n) // applied to the limit only |
1424 | { _outp -= n; VDUI_ONLY(verify_relimit(n)); } |
1425 | |
1426 | bool operator<(DUIterator_Fast& limit) { |
1427 | I_VDUI_ONLY(*this, this->verify(_node, true)); |
1428 | I_VDUI_ONLY(limit, limit.verify_limit()); |
1429 | return _outp < limit._outp; |
1430 | } |
1431 | |
1432 | void operator=(const DUIterator_Fast& that) |
1433 | { _outp = that._outp; debug_only(reset(that))reset(that); } |
1434 | }; |
1435 | |
1436 | DUIterator_Fast Node::fast_outs(DUIterator_Fast& imax) const { |
1437 | // Assign a limit pointer to the reference argument: |
1438 | imax = DUIterator_Fast(this, (ptrdiff_t)_outcnt); |
1439 | // Return the base pointer: |
1440 | return DUIterator_Fast(this, 0); |
1441 | } |
1442 | Node* Node::fast_out(DUIterator_Fast& i) const { |
1443 | I_VDUI_ONLY(i, i.verify(this)); |
1444 | return debug_only(i._last=)i._last= *i._outp; |
1445 | } |
1446 | |
1447 | |
1448 | // Faster DU iterator. Requires each successive edge to be removed. |
1449 | // Does not allow insertion of any edges. |
1450 | // Usage: |
1451 | // for (DUIterator_Last imin, i = x->last_outs(imin); i >= imin; i -= num_edges) { |
1452 | // Node* y = x->last_out(i); |
1453 | // ... |
1454 | // } |
1455 | // Compiles in product mode to raw Node** pointer arithmetic, with |
1456 | // no reloading of pointers from the original node x. |
1457 | class DUIterator_Last : private DUIterator_Fast { |
1458 | friend class Node; |
1459 | |
1460 | #ifdef ASSERT1 |
1461 | void verify(const Node* node, bool at_end_ok = false); |
1462 | void verify_limit(); |
1463 | void verify_step(uint num_edges); |
1464 | #endif |
1465 | |
1466 | // Note: offset must be signed, since -1 is sometimes passed |
1467 | DUIterator_Last(const Node* node, ptrdiff_t offset) |
1468 | : DUIterator_Fast(node, offset) { } |
1469 | |
1470 | void operator++(int dummy_to_specify_postfix_op) {} // do not use |
1471 | void operator<(int) {} // do not use |
1472 | |
1473 | public: |
1474 | DUIterator_Last() { } |
1475 | // initialize to garbage |
1476 | |
1477 | DUIterator_Last(const DUIterator_Last& that) = default; |
1478 | |
1479 | void operator--() |
1480 | { _outp--; VDUI_ONLY(verify_step(1)); } |
1481 | |
1482 | void operator-=(uint n) |
1483 | { _outp -= n; VDUI_ONLY(verify_step(n)); } |
1484 | |
1485 | bool operator>=(DUIterator_Last& limit) { |
1486 | I_VDUI_ONLY(*this, this->verify(_node, true)); |
1487 | I_VDUI_ONLY(limit, limit.verify_limit()); |
1488 | return _outp >= limit._outp; |
1489 | } |
1490 | |
1491 | DUIterator_Last& operator=(const DUIterator_Last& that) = default; |
1492 | }; |
1493 | |
1494 | DUIterator_Last Node::last_outs(DUIterator_Last& imin) const { |
1495 | // Assign a limit pointer to the reference argument: |
1496 | imin = DUIterator_Last(this, 0); |
1497 | // Return the initial pointer: |
1498 | return DUIterator_Last(this, (ptrdiff_t)_outcnt - 1); |
1499 | } |
1500 | Node* Node::last_out(DUIterator_Last& i) const { |
1501 | I_VDUI_ONLY(i, i.verify(this)); |
1502 | return debug_only(i._last=)i._last= *i._outp; |
1503 | } |
1504 | |
1505 | #endif //OPTO_DU_ITERATOR_ASSERT |
1506 | |
1507 | #undef I_VDUI_ONLY |
1508 | #undef VDUI_ONLY |
1509 | |
1510 | // An Iterator that truly follows the iterator pattern. Doesn't |
1511 | // support deletion but could be made to. |
1512 | // |
1513 | // for (SimpleDUIterator i(n); i.has_next(); i.next()) { |
1514 | // Node* m = i.get(); |
1515 | // |
1516 | class SimpleDUIterator : public StackObj { |
1517 | private: |
1518 | Node* node; |
1519 | DUIterator_Fast i; |
1520 | DUIterator_Fast imax; |
1521 | public: |
1522 | SimpleDUIterator(Node* n): node(n), i(n->fast_outs(imax)) {} |
1523 | bool has_next() { return i < imax; } |
1524 | void next() { i++; } |
1525 | Node* get() { return node->fast_out(i); } |
1526 | }; |
1527 | |
1528 | |
1529 | //----------------------------------------------------------------------------- |
1530 | // Map dense integer indices to Nodes. Uses classic doubling-array trick. |
1531 | // Abstractly provides an infinite array of Node*'s, initialized to NULL. |
1532 | // Note that the constructor just zeros things, and since I use Arena |
1533 | // allocation I do not need a destructor to reclaim storage. |
1534 | class Node_Array : public ResourceObj { |
1535 | friend class VMStructs; |
1536 | protected: |
1537 | Arena* _a; // Arena to allocate in |
1538 | uint _max; |
1539 | Node** _nodes; |
1540 | void grow( uint i ); // Grow array node to fit |
1541 | public: |
1542 | Node_Array(Arena* a, uint max = OptoNodeListSize) : _a(a), _max(max) { |
1543 | _nodes = NEW_ARENA_ARRAY(a, Node*, max)(Node**) (a)->Amalloc((max) * sizeof(Node*)); |
1544 | clear(); |
1545 | } |
1546 | |
1547 | Node_Array(Node_Array* na) : _a(na->_a), _max(na->_max), _nodes(na->_nodes) {} |
1548 | Node *operator[] ( uint i ) const // Lookup, or NULL for not mapped |
1549 | { return (i<_max) ? _nodes[i] : (Node*)NULL__null; } |
1550 | Node* at(uint i) const { assert(i<_max,"oob")do { if (!(i<_max)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1550, "assert(" "i<_max" ") failed", "oob"); ::breakpoint (); } } while (0); return _nodes[i]; } |
1551 | Node** adr() { return _nodes; } |
1552 | // Extend the mapping: index i maps to Node *n. |
1553 | void map( uint i, Node *n ) { if( i>=_max ) grow(i); _nodes[i] = n; } |
1554 | void insert( uint i, Node *n ); |
1555 | void remove( uint i ); // Remove, preserving order |
1556 | // Clear all entries in _nodes to NULL but keep storage |
1557 | void clear() { |
1558 | Copy::zero_to_bytes(_nodes, _max * sizeof(Node*)); |
1559 | } |
1560 | |
1561 | uint Size() const { return _max; } |
1562 | void dump() const; |
1563 | }; |
1564 | |
1565 | class Node_List : public Node_Array { |
1566 | friend class VMStructs; |
1567 | uint _cnt; |
1568 | public: |
1569 | Node_List(uint max = OptoNodeListSize) : Node_Array(Thread::current()->resource_area(), max), _cnt(0) {} |
1570 | Node_List(Arena *a, uint max = OptoNodeListSize) : Node_Array(a, max), _cnt(0) {} |
1571 | bool contains(const Node* n) const { |
1572 | for (uint e = 0; e < size(); e++) { |
1573 | if (at(e) == n) return true; |
1574 | } |
1575 | return false; |
1576 | } |
1577 | void insert( uint i, Node *n ) { Node_Array::insert(i,n); _cnt++; } |
1578 | void remove( uint i ) { Node_Array::remove(i); _cnt--; } |
1579 | void push( Node *b ) { map(_cnt++,b); } |
1580 | void yank( Node *n ); // Find and remove |
1581 | Node *pop() { return _nodes[--_cnt]; } |
1582 | void clear() { _cnt = 0; Node_Array::clear(); } // retain storage |
1583 | void copy(const Node_List& from) { |
1584 | if (from._max > _max) { |
1585 | grow(from._max); |
1586 | } |
1587 | _cnt = from._cnt; |
1588 | Copy::conjoint_words_to_higher((HeapWord*)&from._nodes[0], (HeapWord*)&_nodes[0], from._max * sizeof(Node*)); |
1589 | } |
1590 | |
1591 | uint size() const { return _cnt; } |
1592 | void dump() const; |
1593 | void dump_simple() const; |
1594 | }; |
1595 | |
1596 | //------------------------------Unique_Node_List------------------------------- |
1597 | class Unique_Node_List : public Node_List { |
1598 | friend class VMStructs; |
1599 | VectorSet _in_worklist; |
1600 | uint _clock_index; // Index in list where to pop from next |
1601 | public: |
1602 | Unique_Node_List() : Node_List(), _clock_index(0) {} |
1603 | Unique_Node_List(Arena *a) : Node_List(a), _in_worklist(a), _clock_index(0) {} |
1604 | |
1605 | void remove( Node *n ); |
1606 | bool member( Node *n ) { return _in_worklist.test(n->_idx) != 0; } |
1607 | VectorSet& member_set(){ return _in_worklist; } |
1608 | |
1609 | void push(Node* b) { |
1610 | if( !_in_worklist.test_set(b->_idx) ) |
1611 | Node_List::push(b); |
1612 | } |
1613 | Node *pop() { |
1614 | if( _clock_index >= size() ) _clock_index = 0; |
1615 | Node *b = at(_clock_index); |
1616 | map( _clock_index, Node_List::pop()); |
1617 | if (size() != 0) _clock_index++; // Always start from 0 |
1618 | _in_worklist.remove(b->_idx); |
1619 | return b; |
1620 | } |
1621 | Node *remove(uint i) { |
1622 | Node *b = Node_List::at(i); |
1623 | _in_worklist.remove(b->_idx); |
1624 | map(i,Node_List::pop()); |
1625 | return b; |
1626 | } |
1627 | void yank(Node *n) { |
1628 | _in_worklist.remove(n->_idx); |
1629 | Node_List::yank(n); |
1630 | } |
1631 | void clear() { |
1632 | _in_worklist.clear(); // Discards storage but grows automatically |
1633 | Node_List::clear(); |
1634 | _clock_index = 0; |
1635 | } |
1636 | |
1637 | // Used after parsing to remove useless nodes before Iterative GVN |
1638 | void remove_useless_nodes(VectorSet& useful); |
1639 | |
1640 | bool contains(const Node* n) const { |
1641 | fatal("use faster member() instead")do { (*g_assert_poison) = 'X';; report_fatal(INTERNAL_ERROR, "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1641, "use faster member() instead"); ::breakpoint(); } while (0); |
1642 | return false; |
1643 | } |
1644 | |
1645 | #ifndef PRODUCT |
1646 | void print_set() const { _in_worklist.print(); } |
1647 | #endif |
1648 | }; |
1649 | |
1650 | // Inline definition of Compile::record_for_igvn must be deferred to this point. |
1651 | inline void Compile::record_for_igvn(Node* n) { |
1652 | _for_igvn->push(n); |
1653 | } |
1654 | |
1655 | //------------------------------Node_Stack------------------------------------- |
1656 | class Node_Stack { |
1657 | friend class VMStructs; |
1658 | protected: |
1659 | struct INode { |
1660 | Node *node; // Processed node |
1661 | uint indx; // Index of next node's child |
1662 | }; |
1663 | INode *_inode_top; // tos, stack grows up |
1664 | INode *_inode_max; // End of _inodes == _inodes + _max |
1665 | INode *_inodes; // Array storage for the stack |
1666 | Arena *_a; // Arena to allocate in |
1667 | void grow(); |
1668 | public: |
1669 | Node_Stack(int size) { |
1670 | size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize; |
1671 | _a = Thread::current()->resource_area(); |
1672 | _inodes = NEW_ARENA_ARRAY( _a, INode, max )(INode*) (_a)->Amalloc((max) * sizeof(INode)); |
1673 | _inode_max = _inodes + max; |
1674 | _inode_top = _inodes - 1; // stack is empty |
1675 | } |
1676 | |
1677 | Node_Stack(Arena *a, int size) : _a(a) { |
1678 | size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize; |
1679 | _inodes = NEW_ARENA_ARRAY( _a, INode, max )(INode*) (_a)->Amalloc((max) * sizeof(INode)); |
1680 | _inode_max = _inodes + max; |
1681 | _inode_top = _inodes - 1; // stack is empty |
1682 | } |
1683 | |
1684 | void pop() { |
1685 | assert(_inode_top >= _inodes, "node stack underflow")do { if (!(_inode_top >= _inodes)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1685, "assert(" "_inode_top >= _inodes" ") failed", "node stack underflow" ); ::breakpoint(); } } while (0); |
1686 | --_inode_top; |
1687 | } |
1688 | void push(Node *n, uint i) { |
1689 | ++_inode_top; |
1690 | if (_inode_top >= _inode_max) grow(); |
1691 | INode *top = _inode_top; // optimization |
1692 | top->node = n; |
1693 | top->indx = i; |
1694 | } |
1695 | Node *node() const { |
1696 | return _inode_top->node; |
1697 | } |
1698 | Node* node_at(uint i) const { |
1699 | assert(_inodes + i <= _inode_top, "in range")do { if (!(_inodes + i <= _inode_top)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1699, "assert(" "_inodes + i <= _inode_top" ") failed", "in range" ); ::breakpoint(); } } while (0); |
1700 | return _inodes[i].node; |
1701 | } |
1702 | uint index() const { |
1703 | return _inode_top->indx; |
1704 | } |
1705 | uint index_at(uint i) const { |
1706 | assert(_inodes + i <= _inode_top, "in range")do { if (!(_inodes + i <= _inode_top)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1706, "assert(" "_inodes + i <= _inode_top" ") failed", "in range" ); ::breakpoint(); } } while (0); |
1707 | return _inodes[i].indx; |
1708 | } |
1709 | void set_node(Node *n) { |
1710 | _inode_top->node = n; |
1711 | } |
1712 | void set_index(uint i) { |
1713 | _inode_top->indx = i; |
1714 | } |
1715 | uint size_max() const { return (uint)pointer_delta(_inode_max, _inodes, sizeof(INode)); } // Max size |
1716 | uint size() const { return (uint)pointer_delta((_inode_top+1), _inodes, sizeof(INode)); } // Current size |
1717 | bool is_nonempty() const { return (_inode_top >= _inodes); } |
1718 | bool is_empty() const { return (_inode_top < _inodes); } |
1719 | void clear() { _inode_top = _inodes - 1; } // retain storage |
1720 | |
1721 | // Node_Stack is used to map nodes. |
1722 | Node* find(uint idx) const; |
1723 | }; |
1724 | |
1725 | |
1726 | //-----------------------------Node_Notes-------------------------------------- |
1727 | // Debugging or profiling annotations loosely and sparsely associated |
1728 | // with some nodes. See Compile::node_notes_at for the accessor. |
1729 | class Node_Notes { |
1730 | friend class VMStructs; |
1731 | JVMState* _jvms; |
1732 | |
1733 | public: |
1734 | Node_Notes(JVMState* jvms = NULL__null) { |
1735 | _jvms = jvms; |
1736 | } |
1737 | |
1738 | JVMState* jvms() { return _jvms; } |
1739 | void set_jvms(JVMState* x) { _jvms = x; } |
1740 | |
1741 | // True if there is nothing here. |
1742 | bool is_clear() { |
1743 | return (_jvms == NULL__null); |
1744 | } |
1745 | |
1746 | // Make there be nothing here. |
1747 | void clear() { |
1748 | _jvms = NULL__null; |
1749 | } |
1750 | |
1751 | // Make a new, clean node notes. |
1752 | static Node_Notes* make(Compile* C) { |
1753 | Node_Notes* nn = NEW_ARENA_ARRAY(C->comp_arena(), Node_Notes, 1)(Node_Notes*) (C->comp_arena())->Amalloc((1) * sizeof(Node_Notes )); |
1754 | nn->clear(); |
1755 | return nn; |
1756 | } |
1757 | |
1758 | Node_Notes* clone(Compile* C) { |
1759 | Node_Notes* nn = NEW_ARENA_ARRAY(C->comp_arena(), Node_Notes, 1)(Node_Notes*) (C->comp_arena())->Amalloc((1) * sizeof(Node_Notes )); |
1760 | (*nn) = (*this); |
1761 | return nn; |
1762 | } |
1763 | |
1764 | // Absorb any information from source. |
1765 | bool update_from(Node_Notes* source) { |
1766 | bool changed = false; |
1767 | if (source != NULL__null) { |
1768 | if (source->jvms() != NULL__null) { |
1769 | set_jvms(source->jvms()); |
1770 | changed = true; |
1771 | } |
1772 | } |
1773 | return changed; |
1774 | } |
1775 | }; |
1776 | |
1777 | // Inlined accessors for Compile::node_nodes that require the preceding class: |
1778 | inline Node_Notes* |
1779 | Compile::locate_node_notes(GrowableArray<Node_Notes*>* arr, |
1780 | int idx, bool can_grow) { |
1781 | assert(idx >= 0, "oob")do { if (!(idx >= 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1781, "assert(" "idx >= 0" ") failed", "oob"); ::breakpoint (); } } while (0); |
1782 | int block_idx = (idx >> _log2_node_notes_block_size); |
1783 | int grow_by = (block_idx - (arr == NULL__null? 0: arr->length())); |
1784 | if (grow_by >= 0) { |
1785 | if (!can_grow) return NULL__null; |
1786 | grow_node_notes(arr, grow_by + 1); |
1787 | } |
1788 | if (arr == NULL__null) return NULL__null; |
1789 | // (Every element of arr is a sub-array of length _node_notes_block_size.) |
1790 | return arr->at(block_idx) + (idx & (_node_notes_block_size-1)); |
1791 | } |
1792 | |
1793 | inline bool |
1794 | Compile::set_node_notes_at(int idx, Node_Notes* value) { |
1795 | if (value == NULL__null || value->is_clear()) |
1796 | return false; // nothing to write => write nothing |
1797 | Node_Notes* loc = locate_node_notes(_node_note_array, idx, true); |
1798 | assert(loc != NULL, "")do { if (!(loc != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1798, "assert(" "loc != __null" ") failed", ""); ::breakpoint (); } } while (0); |
1799 | return loc->update_from(value); |
1800 | } |
1801 | |
1802 | |
1803 | //------------------------------TypeNode--------------------------------------- |
1804 | // Node with a Type constant. |
1805 | class TypeNode : public Node { |
1806 | protected: |
1807 | virtual uint hash() const; // Check the type |
1808 | virtual bool cmp( const Node &n ) const; |
1809 | virtual uint size_of() const; // Size is bigger |
1810 | const Type* const _type; |
1811 | public: |
1812 | void set_type(const Type* t) { |
1813 | assert(t != NULL, "sanity")do { if (!(t != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1813, "assert(" "t != __null" ") failed", "sanity"); ::breakpoint (); } } while (0); |
1814 | debug_only(uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH)uint check_hash = (VerifyHashTableKeys && _hash_lock) ? hash() : NO_HASH; |
1815 | *(const Type**)&_type = t; // cast away const-ness |
1816 | // If this node is in the hash table, make sure it doesn't need a rehash. |
1817 | assert(check_hash == NO_HASH || check_hash == hash(), "type change must preserve hash code")do { if (!(check_hash == NO_HASH || check_hash == hash())) { ( *g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1817, "assert(" "check_hash == NO_HASH || check_hash == hash()" ") failed", "type change must preserve hash code"); ::breakpoint (); } } while (0); |
1818 | } |
1819 | const Type* type() const { assert(_type != NULL, "sanity")do { if (!(_type != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1819, "assert(" "_type != __null" ") failed", "sanity"); :: breakpoint(); } } while (0); return _type; }; |
1820 | TypeNode( const Type *t, uint required ) : Node(required), _type(t) { |
1821 | init_class_id(Class_Type); |
1822 | } |
1823 | virtual const Type* Value(PhaseGVN* phase) const; |
1824 | virtual const Type *bottom_type() const; |
1825 | virtual uint ideal_reg() const; |
1826 | #ifndef PRODUCT |
1827 | virtual void dump_spec(outputStream *st) const; |
1828 | virtual void dump_compact_spec(outputStream *st) const; |
1829 | #endif |
1830 | }; |
1831 | |
1832 | #include "opto/opcodes.hpp" |
1833 | |
1834 | #define Op_IL(op)inline int Op_op(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1834, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_opI ; } return Op_opL; } \ |
1835 | inline int Op_ ## op(BasicType bt) { \ |
1836 | assert(bt == T_INT || bt == T_LONG, "only for int or longs")do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1836, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); \ |
1837 | if (bt == T_INT) { \ |
1838 | return Op_## op ## I; \ |
1839 | } \ |
1840 | return Op_## op ## L; \ |
1841 | } |
1842 | |
1843 | Op_IL(Add)inline int Op_Add(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1843, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_AddI ; } return Op_AddL; } |
1844 | Op_IL(Sub)inline int Op_Sub(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1844, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_SubI ; } return Op_SubL; } |
1845 | Op_IL(Mul)inline int Op_Mul(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1845, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_MulI ; } return Op_MulL; } |
1846 | Op_IL(URShift)inline int Op_URShift(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1846, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_URShiftI ; } return Op_URShiftL; } |
1847 | Op_IL(LShift)inline int Op_LShift(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1847, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_LShiftI ; } return Op_LShiftL; } |
1848 | Op_IL(Xor)inline int Op_Xor(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1848, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_XorI ; } return Op_XorL; } |
1849 | Op_IL(Cmp)inline int Op_Cmp(BasicType bt) { do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1849, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); if (bt == T_INT) { return Op_CmpI ; } return Op_CmpL; } |
1850 | |
1851 | inline int Op_Cmp_unsigned(BasicType bt) { |
1852 | assert(bt == T_INT || bt == T_LONG, "only for int or longs")do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1852, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); |
1853 | if (bt == T_INT) { |
1854 | return Op_CmpU; |
1855 | } |
1856 | return Op_CmpUL; |
1857 | } |
1858 | |
1859 | inline int Op_Cast(BasicType bt) { |
1860 | assert(bt == T_INT || bt == T_LONG, "only for int or longs")do { if (!(bt == T_INT || bt == T_LONG)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/node.hpp" , 1860, "assert(" "bt == T_INT || bt == T_LONG" ") failed", "only for int or longs" ); ::breakpoint(); } } while (0); |
1861 | if (bt == T_INT) { |
1862 | return Op_CastII; |
1863 | } |
1864 | return Op_CastLL; |
1865 | } |
1866 | |
1867 | #endif // SHARE_OPTO_NODE_HPP |
1 | /* | |||
2 | * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. | |||
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 | * | |||
19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |||
20 | * or visit www.oracle.com if you need additional information or have any | |||
21 | * questions. | |||
22 | * | |||
23 | */ | |||
24 | ||||
25 | #ifndef SHARE_OPTO_LOOPNODE_HPP | |||
26 | #define SHARE_OPTO_LOOPNODE_HPP | |||
27 | ||||
28 | #include "opto/cfgnode.hpp" | |||
29 | #include "opto/multnode.hpp" | |||
30 | #include "opto/phaseX.hpp" | |||
31 | #include "opto/subnode.hpp" | |||
32 | #include "opto/type.hpp" | |||
33 | ||||
34 | class CmpNode; | |||
35 | class BaseCountedLoopEndNode; | |||
36 | class CountedLoopNode; | |||
37 | class IdealLoopTree; | |||
38 | class LoopNode; | |||
39 | class Node; | |||
40 | class OuterStripMinedLoopEndNode; | |||
41 | class PathFrequency; | |||
42 | class PhaseIdealLoop; | |||
43 | class CountedLoopReserveKit; | |||
44 | class VectorSet; | |||
45 | class Invariance; | |||
46 | struct small_cache; | |||
47 | ||||
48 | // | |||
49 | // I D E A L I Z E D L O O P S | |||
50 | // | |||
51 | // Idealized loops are the set of loops I perform more interesting | |||
52 | // transformations on, beyond simple hoisting. | |||
53 | ||||
54 | //------------------------------LoopNode--------------------------------------- | |||
55 | // Simple loop header. Fall in path on left, loop-back path on right. | |||
56 | class LoopNode : public RegionNode { | |||
57 | // Size is bigger to hold the flags. However, the flags do not change | |||
58 | // the semantics so it does not appear in the hash & cmp functions. | |||
59 | virtual uint size_of() const { return sizeof(*this); } | |||
60 | protected: | |||
61 | uint _loop_flags; | |||
62 | // Names for flag bitfields | |||
63 | enum { Normal=0, Pre=1, Main=2, Post=3, PreMainPostFlagsMask=3, | |||
64 | MainHasNoPreLoop = 1<<2, | |||
65 | HasExactTripCount = 1<<3, | |||
66 | InnerLoop = 1<<4, | |||
67 | PartialPeelLoop = 1<<5, | |||
68 | PartialPeelFailed = 1<<6, | |||
69 | HasReductions = 1<<7, | |||
70 | WasSlpAnalyzed = 1<<8, | |||
71 | PassedSlpAnalysis = 1<<9, | |||
72 | DoUnrollOnly = 1<<10, | |||
73 | VectorizedLoop = 1<<11, | |||
74 | HasAtomicPostLoop = 1<<12, | |||
75 | HasRangeChecks = 1<<13, | |||
76 | IsMultiversioned = 1<<14, | |||
77 | StripMined = 1<<15, | |||
78 | SubwordLoop = 1<<16, | |||
79 | ProfileTripFailed = 1<<17, | |||
80 | LoopNestInnerLoop = 1 << 18, | |||
81 | LoopNestLongOuterLoop = 1 << 19}; | |||
82 | char _unswitch_count; | |||
83 | enum { _unswitch_max=3 }; | |||
84 | char _postloop_flags; | |||
85 | enum { LoopNotRCEChecked = 0, LoopRCEChecked = 1, RCEPostLoop = 2 }; | |||
86 | ||||
87 | // Expected trip count from profile data | |||
88 | float _profile_trip_cnt; | |||
89 | ||||
90 | public: | |||
91 | // Names for edge indices | |||
92 | enum { Self=0, EntryControl, LoopBackControl }; | |||
93 | ||||
94 | bool is_inner_loop() const { return _loop_flags & InnerLoop; } | |||
95 | void set_inner_loop() { _loop_flags |= InnerLoop; } | |||
96 | ||||
97 | bool range_checks_present() const { return _loop_flags & HasRangeChecks; } | |||
98 | bool is_multiversioned() const { return _loop_flags & IsMultiversioned; } | |||
99 | bool is_vectorized_loop() const { return _loop_flags & VectorizedLoop; } | |||
100 | bool is_partial_peel_loop() const { return _loop_flags & PartialPeelLoop; } | |||
101 | void set_partial_peel_loop() { _loop_flags |= PartialPeelLoop; } | |||
102 | bool partial_peel_has_failed() const { return _loop_flags & PartialPeelFailed; } | |||
103 | bool is_strip_mined() const { return _loop_flags & StripMined; } | |||
104 | bool is_profile_trip_failed() const { return _loop_flags & ProfileTripFailed; } | |||
105 | bool is_subword_loop() const { return _loop_flags & SubwordLoop; } | |||
106 | bool is_loop_nest_inner_loop() const { return _loop_flags & LoopNestInnerLoop; } | |||
107 | bool is_loop_nest_outer_loop() const { return _loop_flags & LoopNestLongOuterLoop; } | |||
108 | ||||
109 | void mark_partial_peel_failed() { _loop_flags |= PartialPeelFailed; } | |||
110 | void mark_has_reductions() { _loop_flags |= HasReductions; } | |||
111 | void mark_was_slp() { _loop_flags |= WasSlpAnalyzed; } | |||
112 | void mark_passed_slp() { _loop_flags |= PassedSlpAnalysis; } | |||
113 | void mark_do_unroll_only() { _loop_flags |= DoUnrollOnly; } | |||
114 | void mark_loop_vectorized() { _loop_flags |= VectorizedLoop; } | |||
115 | void mark_has_atomic_post_loop() { _loop_flags |= HasAtomicPostLoop; } | |||
116 | void mark_has_range_checks() { _loop_flags |= HasRangeChecks; } | |||
117 | void mark_is_multiversioned() { _loop_flags |= IsMultiversioned; } | |||
118 | void mark_strip_mined() { _loop_flags |= StripMined; } | |||
119 | void clear_strip_mined() { _loop_flags &= ~StripMined; } | |||
120 | void mark_profile_trip_failed() { _loop_flags |= ProfileTripFailed; } | |||
121 | void mark_subword_loop() { _loop_flags |= SubwordLoop; } | |||
122 | void mark_loop_nest_inner_loop() { _loop_flags |= LoopNestInnerLoop; } | |||
123 | void mark_loop_nest_outer_loop() { _loop_flags |= LoopNestLongOuterLoop; } | |||
124 | ||||
125 | int unswitch_max() { return _unswitch_max; } | |||
126 | int unswitch_count() { return _unswitch_count; } | |||
127 | ||||
128 | int has_been_range_checked() const { return _postloop_flags & LoopRCEChecked; } | |||
129 | void set_has_been_range_checked() { _postloop_flags |= LoopRCEChecked; } | |||
130 | int is_rce_post_loop() const { return _postloop_flags & RCEPostLoop; } | |||
131 | void set_is_rce_post_loop() { _postloop_flags |= RCEPostLoop; } | |||
132 | ||||
133 | void set_unswitch_count(int val) { | |||
134 | assert (val <= unswitch_max(), "too many unswitches")do { if (!(val <= unswitch_max())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 134, "assert(" "val <= unswitch_max()" ") failed", "too many unswitches" ); ::breakpoint(); } } while (0); | |||
135 | _unswitch_count = val; | |||
136 | } | |||
137 | ||||
138 | void set_profile_trip_cnt(float ptc) { _profile_trip_cnt = ptc; } | |||
139 | float profile_trip_cnt() { return _profile_trip_cnt; } | |||
140 | ||||
141 | LoopNode(Node *entry, Node *backedge) | |||
142 | : RegionNode(3), _loop_flags(0), _unswitch_count(0), | |||
143 | _postloop_flags(0), _profile_trip_cnt(COUNT_UNKNOWN(-1.0f)) { | |||
144 | init_class_id(Class_Loop); | |||
145 | init_req(EntryControl, entry); | |||
146 | init_req(LoopBackControl, backedge); | |||
147 | } | |||
148 | ||||
149 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |||
150 | virtual int Opcode() const; | |||
151 | bool can_be_counted_loop(PhaseTransform* phase) const { | |||
152 | return req() == 3 && in(0) != NULL__null && | |||
153 | in(1) != NULL__null && phase->type(in(1)) != Type::TOP && | |||
154 | in(2) != NULL__null && phase->type(in(2)) != Type::TOP; | |||
155 | } | |||
156 | bool is_valid_counted_loop(BasicType bt) const; | |||
157 | #ifndef PRODUCT | |||
158 | virtual void dump_spec(outputStream *st) const; | |||
159 | #endif | |||
160 | ||||
161 | void verify_strip_mined(int expect_skeleton) const NOT_DEBUG_RETURN; | |||
162 | virtual LoopNode* skip_strip_mined(int expect_skeleton = 1) { return this; } | |||
163 | virtual IfTrueNode* outer_loop_tail() const { ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 163); ::breakpoint(); } while (0); return NULL__null; } | |||
164 | virtual OuterStripMinedLoopEndNode* outer_loop_end() const { ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 164); ::breakpoint(); } while (0); return NULL__null; } | |||
165 | virtual IfFalseNode* outer_loop_exit() const { ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 165); ::breakpoint(); } while (0); return NULL__null; } | |||
166 | virtual SafePointNode* outer_safepoint() const { ShouldNotReachHere()do { (*g_assert_poison) = 'X';; report_should_not_reach_here( "/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 166); ::breakpoint(); } while (0); return NULL__null; } | |||
167 | }; | |||
168 | ||||
169 | //------------------------------Counted Loops---------------------------------- | |||
170 | // Counted loops are all trip-counted loops, with exactly 1 trip-counter exit | |||
171 | // path (and maybe some other exit paths). The trip-counter exit is always | |||
172 | // last in the loop. The trip-counter have to stride by a constant; | |||
173 | // the exit value is also loop invariant. | |||
174 | ||||
175 | // CountedLoopNodes and CountedLoopEndNodes come in matched pairs. The | |||
176 | // CountedLoopNode has the incoming loop control and the loop-back-control | |||
177 | // which is always the IfTrue before the matching CountedLoopEndNode. The | |||
178 | // CountedLoopEndNode has an incoming control (possibly not the | |||
179 | // CountedLoopNode if there is control flow in the loop), the post-increment | |||
180 | // trip-counter value, and the limit. The trip-counter value is always of | |||
181 | // the form (Op old-trip-counter stride). The old-trip-counter is produced | |||
182 | // by a Phi connected to the CountedLoopNode. The stride is constant. | |||
183 | // The Op is any commutable opcode, including Add, Mul, Xor. The | |||
184 | // CountedLoopEndNode also takes in the loop-invariant limit value. | |||
185 | ||||
186 | // From a CountedLoopNode I can reach the matching CountedLoopEndNode via the | |||
187 | // loop-back control. From CountedLoopEndNodes I can reach CountedLoopNodes | |||
188 | // via the old-trip-counter from the Op node. | |||
189 | ||||
190 | //------------------------------CountedLoopNode-------------------------------- | |||
191 | // CountedLoopNodes head simple counted loops. CountedLoopNodes have as | |||
192 | // inputs the incoming loop-start control and the loop-back control, so they | |||
193 | // act like RegionNodes. They also take in the initial trip counter, the | |||
194 | // loop-invariant stride and the loop-invariant limit value. CountedLoopNodes | |||
195 | // produce a loop-body control and the trip counter value. Since | |||
196 | // CountedLoopNodes behave like RegionNodes I still have a standard CFG model. | |||
197 | ||||
198 | class BaseCountedLoopNode : public LoopNode { | |||
199 | public: | |||
200 | BaseCountedLoopNode(Node *entry, Node *backedge) | |||
201 | : LoopNode(entry, backedge) { | |||
202 | } | |||
203 | ||||
204 | Node *init_control() const { return in(EntryControl); } | |||
205 | Node *back_control() const { return in(LoopBackControl); } | |||
206 | ||||
207 | Node* init_trip() const; | |||
208 | Node* stride() const; | |||
209 | bool stride_is_con() const; | |||
210 | Node* limit() const; | |||
211 | Node* incr() const; | |||
212 | Node* phi() const; | |||
213 | ||||
214 | BaseCountedLoopEndNode* loopexit_or_null() const; | |||
215 | BaseCountedLoopEndNode* loopexit() const; | |||
216 | ||||
217 | virtual BasicType bt() const = 0; | |||
218 | ||||
219 | jlong stride_con() const; | |||
220 | ||||
221 | static BaseCountedLoopNode* make(Node* entry, Node* backedge, BasicType bt); | |||
222 | }; | |||
223 | ||||
224 | ||||
225 | class CountedLoopNode : public BaseCountedLoopNode { | |||
226 | // Size is bigger to hold _main_idx. However, _main_idx does not change | |||
227 | // the semantics so it does not appear in the hash & cmp functions. | |||
228 | virtual uint size_of() const { return sizeof(*this); } | |||
229 | ||||
230 | // For Pre- and Post-loops during debugging ONLY, this holds the index of | |||
231 | // the Main CountedLoop. Used to assert that we understand the graph shape. | |||
232 | node_idx_t _main_idx; | |||
233 | ||||
234 | // Known trip count calculated by compute_exact_trip_count() | |||
235 | uint _trip_count; | |||
236 | ||||
237 | // Log2 of original loop bodies in unrolled loop | |||
238 | int _unrolled_count_log2; | |||
239 | ||||
240 | // Node count prior to last unrolling - used to decide if | |||
241 | // unroll,optimize,unroll,optimize,... is making progress | |||
242 | int _node_count_before_unroll; | |||
243 | ||||
244 | // If slp analysis is performed we record the maximum | |||
245 | // vector mapped unroll factor here | |||
246 | int _slp_maximum_unroll_factor; | |||
247 | ||||
248 | public: | |||
249 | CountedLoopNode(Node *entry, Node *backedge) | |||
250 | : BaseCountedLoopNode(entry, backedge), _main_idx(0), _trip_count(max_juint), | |||
251 | _unrolled_count_log2(0), _node_count_before_unroll(0), | |||
252 | _slp_maximum_unroll_factor(0) { | |||
253 | init_class_id(Class_CountedLoop); | |||
254 | // Initialize _trip_count to the largest possible value. | |||
255 | // Will be reset (lower) if the loop's trip count is known. | |||
256 | } | |||
257 | ||||
258 | virtual int Opcode() const; | |||
259 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |||
260 | ||||
261 | CountedLoopEndNode* loopexit_or_null() const { return (CountedLoopEndNode*) BaseCountedLoopNode::loopexit_or_null(); } | |||
262 | CountedLoopEndNode* loopexit() const { return (CountedLoopEndNode*) BaseCountedLoopNode::loopexit(); } | |||
263 | int stride_con() const; | |||
264 | ||||
265 | // Match increment with optional truncation | |||
266 | static Node* | |||
267 | match_incr_with_optional_truncation(Node* expr, Node** trunc1, Node** trunc2, const TypeInteger** trunc_type, | |||
268 | BasicType bt); | |||
269 | ||||
270 | // A 'main' loop has a pre-loop and a post-loop. The 'main' loop | |||
271 | // can run short a few iterations and may start a few iterations in. | |||
272 | // It will be RCE'd and unrolled and aligned. | |||
273 | ||||
274 | // A following 'post' loop will run any remaining iterations. Used | |||
275 | // during Range Check Elimination, the 'post' loop will do any final | |||
276 | // iterations with full checks. Also used by Loop Unrolling, where | |||
277 | // the 'post' loop will do any epilog iterations needed. Basically, | |||
278 | // a 'post' loop can not profitably be further unrolled or RCE'd. | |||
279 | ||||
280 | // A preceding 'pre' loop will run at least 1 iteration (to do peeling), | |||
281 | // it may do under-flow checks for RCE and may do alignment iterations | |||
282 | // so the following main loop 'knows' that it is striding down cache | |||
283 | // lines. | |||
284 | ||||
285 | // A 'main' loop that is ONLY unrolled or peeled, never RCE'd or | |||
286 | // Aligned, may be missing it's pre-loop. | |||
287 | bool is_normal_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Normal; } | |||
288 | bool is_pre_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Pre; } | |||
289 | bool is_main_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Main; } | |||
290 | bool is_post_loop () const { return (_loop_flags&PreMainPostFlagsMask) == Post; } | |||
291 | bool is_reduction_loop() const { return (_loop_flags&HasReductions) == HasReductions; } | |||
292 | bool was_slp_analyzed () const { return (_loop_flags&WasSlpAnalyzed) == WasSlpAnalyzed; } | |||
293 | bool has_passed_slp () const { return (_loop_flags&PassedSlpAnalysis) == PassedSlpAnalysis; } | |||
294 | bool is_unroll_only () const { return (_loop_flags&DoUnrollOnly) == DoUnrollOnly; } | |||
295 | bool is_main_no_pre_loop() const { return _loop_flags & MainHasNoPreLoop; } | |||
296 | bool has_atomic_post_loop () const { return (_loop_flags & HasAtomicPostLoop) == HasAtomicPostLoop; } | |||
297 | void set_main_no_pre_loop() { _loop_flags |= MainHasNoPreLoop; } | |||
298 | ||||
299 | int main_idx() const { return _main_idx; } | |||
300 | ||||
301 | ||||
302 | void set_pre_loop (CountedLoopNode *main) { assert(is_normal_loop(),"")do { if (!(is_normal_loop())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 302, "assert(" "is_normal_loop()" ") failed", ""); ::breakpoint (); } } while (0); _loop_flags |= Pre ; _main_idx = main->_idx; } | |||
303 | void set_main_loop ( ) { assert(is_normal_loop(),"")do { if (!(is_normal_loop())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 303, "assert(" "is_normal_loop()" ") failed", ""); ::breakpoint (); } } while (0); _loop_flags |= Main; } | |||
304 | void set_post_loop (CountedLoopNode *main) { assert(is_normal_loop(),"")do { if (!(is_normal_loop())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 304, "assert(" "is_normal_loop()" ") failed", ""); ::breakpoint (); } } while (0); _loop_flags |= Post; _main_idx = main->_idx; } | |||
305 | void set_normal_loop( ) { _loop_flags &= ~PreMainPostFlagsMask; } | |||
306 | ||||
307 | void set_trip_count(uint tc) { _trip_count = tc; } | |||
308 | uint trip_count() { return _trip_count; } | |||
309 | ||||
310 | bool has_exact_trip_count() const { return (_loop_flags & HasExactTripCount) != 0; } | |||
311 | void set_exact_trip_count(uint tc) { | |||
312 | _trip_count = tc; | |||
313 | _loop_flags |= HasExactTripCount; | |||
314 | } | |||
315 | void set_nonexact_trip_count() { | |||
316 | _loop_flags &= ~HasExactTripCount; | |||
317 | } | |||
318 | void set_notpassed_slp() { | |||
319 | _loop_flags &= ~PassedSlpAnalysis; | |||
320 | } | |||
321 | ||||
322 | void double_unrolled_count() { _unrolled_count_log2++; } | |||
323 | int unrolled_count() { return 1 << MIN2(_unrolled_count_log2, BitsPerInt-3); } | |||
324 | ||||
325 | void set_node_count_before_unroll(int ct) { _node_count_before_unroll = ct; } | |||
326 | int node_count_before_unroll() { return _node_count_before_unroll; } | |||
327 | void set_slp_max_unroll(int unroll_factor) { _slp_maximum_unroll_factor = unroll_factor; } | |||
328 | int slp_max_unroll() const { return _slp_maximum_unroll_factor; } | |||
329 | ||||
330 | virtual LoopNode* skip_strip_mined(int expect_skeleton = 1); | |||
331 | OuterStripMinedLoopNode* outer_loop() const; | |||
332 | virtual IfTrueNode* outer_loop_tail() const; | |||
333 | virtual OuterStripMinedLoopEndNode* outer_loop_end() const; | |||
334 | virtual IfFalseNode* outer_loop_exit() const; | |||
335 | virtual SafePointNode* outer_safepoint() const; | |||
336 | ||||
337 | // If this is a main loop in a pre/main/post loop nest, walk over | |||
338 | // the predicates that were inserted by | |||
339 | // duplicate_predicates()/add_range_check_predicate() | |||
340 | static Node* skip_predicates_from_entry(Node* ctrl); | |||
341 | Node* skip_predicates(); | |||
342 | ||||
343 | virtual BasicType bt() const { | |||
344 | return T_INT; | |||
345 | } | |||
346 | ||||
347 | Node* is_canonical_loop_entry(); | |||
348 | ||||
349 | #ifndef PRODUCT | |||
350 | virtual void dump_spec(outputStream *st) const; | |||
351 | #endif | |||
352 | }; | |||
353 | ||||
354 | class LongCountedLoopNode : public BaseCountedLoopNode { | |||
355 | public: | |||
356 | LongCountedLoopNode(Node *entry, Node *backedge) | |||
357 | : BaseCountedLoopNode(entry, backedge) { | |||
358 | init_class_id(Class_LongCountedLoop); | |||
359 | } | |||
360 | ||||
361 | virtual int Opcode() const; | |||
362 | ||||
363 | virtual BasicType bt() const { | |||
364 | return T_LONG; | |||
365 | } | |||
366 | ||||
367 | LongCountedLoopEndNode* loopexit_or_null() const { return (LongCountedLoopEndNode*) BaseCountedLoopNode::loopexit_or_null(); } | |||
368 | LongCountedLoopEndNode* loopexit() const { return (LongCountedLoopEndNode*) BaseCountedLoopNode::loopexit(); } | |||
369 | }; | |||
370 | ||||
371 | ||||
372 | //------------------------------CountedLoopEndNode----------------------------- | |||
373 | // CountedLoopEndNodes end simple trip counted loops. They act much like | |||
374 | // IfNodes. | |||
375 | ||||
376 | class BaseCountedLoopEndNode : public IfNode { | |||
377 | public: | |||
378 | enum { TestControl, TestValue }; | |||
379 | BaseCountedLoopEndNode(Node *control, Node *test, float prob, float cnt) | |||
380 | : IfNode(control, test, prob, cnt) { | |||
381 | init_class_id(Class_BaseCountedLoopEnd); | |||
382 | } | |||
383 | ||||
384 | Node *cmp_node() const { return (in(TestValue)->req() >=2) ? in(TestValue)->in(1) : NULL__null; } | |||
385 | Node* incr() const { Node* tmp = cmp_node(); return (tmp && tmp->req() == 3) ? tmp->in(1) : NULL__null; } | |||
386 | Node* limit() const { Node* tmp = cmp_node(); return (tmp && tmp->req() == 3) ? tmp->in(2) : NULL__null; } | |||
387 | Node* stride() const { Node* tmp = incr(); return (tmp && tmp->req() == 3) ? tmp->in(2) : NULL__null; } | |||
388 | Node* init_trip() const { Node* tmp = phi(); return (tmp && tmp->req() == 3) ? tmp->in(1) : NULL__null; } | |||
389 | bool stride_is_con() const { Node *tmp = stride(); return (tmp != NULL__null && tmp->is_Con()); } | |||
390 | ||||
391 | PhiNode* phi() const { | |||
392 | Node* tmp = incr(); | |||
393 | if (tmp && tmp->req() == 3) { | |||
394 | Node* phi = tmp->in(1); | |||
395 | if (phi->is_Phi()) { | |||
396 | return phi->as_Phi(); | |||
397 | } | |||
398 | } | |||
399 | return NULL__null; | |||
400 | } | |||
401 | ||||
402 | BaseCountedLoopNode* loopnode() const { | |||
403 | // The CountedLoopNode that goes with this CountedLoopEndNode may | |||
404 | // have been optimized out by the IGVN so be cautious with the | |||
405 | // pattern matching on the graph | |||
406 | PhiNode* iv_phi = phi(); | |||
407 | if (iv_phi == NULL__null) { | |||
408 | return NULL__null; | |||
409 | } | |||
410 | Node* ln = iv_phi->in(0); | |||
411 | if (!ln->is_BaseCountedLoop() || ln->as_BaseCountedLoop()->loopexit_or_null() != this) { | |||
412 | return NULL__null; | |||
413 | } | |||
414 | if (ln->as_BaseCountedLoop()->bt() != bt()) { | |||
415 | return NULL__null; | |||
416 | } | |||
417 | return ln->as_BaseCountedLoop(); | |||
418 | } | |||
419 | ||||
420 | BoolTest::mask test_trip() const { return in(TestValue)->as_Bool()->_test._test; } | |||
421 | ||||
422 | jlong stride_con() const; | |||
423 | virtual BasicType bt() const = 0; | |||
424 | ||||
425 | static BaseCountedLoopEndNode* make(Node* control, Node* test, float prob, float cnt, BasicType bt); | |||
426 | }; | |||
427 | ||||
428 | class CountedLoopEndNode : public BaseCountedLoopEndNode { | |||
429 | public: | |||
430 | ||||
431 | CountedLoopEndNode(Node *control, Node *test, float prob, float cnt) | |||
432 | : BaseCountedLoopEndNode(control, test, prob, cnt) { | |||
433 | init_class_id(Class_CountedLoopEnd); | |||
434 | } | |||
435 | virtual int Opcode() const; | |||
436 | ||||
437 | CountedLoopNode* loopnode() const { | |||
438 | return (CountedLoopNode*) BaseCountedLoopEndNode::loopnode(); | |||
439 | } | |||
440 | ||||
441 | virtual BasicType bt() const { | |||
442 | return T_INT; | |||
443 | } | |||
444 | ||||
445 | #ifndef PRODUCT | |||
446 | virtual void dump_spec(outputStream *st) const; | |||
447 | #endif | |||
448 | }; | |||
449 | ||||
450 | class LongCountedLoopEndNode : public BaseCountedLoopEndNode { | |||
451 | public: | |||
452 | LongCountedLoopEndNode(Node *control, Node *test, float prob, float cnt) | |||
453 | : BaseCountedLoopEndNode(control, test, prob, cnt) { | |||
454 | init_class_id(Class_LongCountedLoopEnd); | |||
455 | } | |||
456 | ||||
457 | LongCountedLoopNode* loopnode() const { | |||
458 | return (LongCountedLoopNode*) BaseCountedLoopEndNode::loopnode(); | |||
459 | } | |||
460 | ||||
461 | virtual int Opcode() const; | |||
462 | ||||
463 | virtual BasicType bt() const { | |||
464 | return T_LONG; | |||
465 | } | |||
466 | }; | |||
467 | ||||
468 | ||||
469 | inline BaseCountedLoopEndNode* BaseCountedLoopNode::loopexit_or_null() const { | |||
470 | Node* bctrl = back_control(); | |||
471 | if (bctrl == NULL__null) return NULL__null; | |||
472 | ||||
473 | Node* lexit = bctrl->in(0); | |||
474 | if (!lexit->is_BaseCountedLoopEnd()) { | |||
475 | return NULL__null; | |||
476 | } | |||
477 | BaseCountedLoopEndNode* result = lexit->as_BaseCountedLoopEnd(); | |||
478 | if (result->bt() != bt()) { | |||
479 | return NULL__null; | |||
480 | } | |||
481 | return result; | |||
482 | } | |||
483 | ||||
484 | inline BaseCountedLoopEndNode* BaseCountedLoopNode::loopexit() const { | |||
485 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
486 | assert(cle != NULL, "loopexit is NULL")do { if (!(cle != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 486, "assert(" "cle != __null" ") failed", "loopexit is NULL" ); ::breakpoint(); } } while (0); | |||
487 | return cle; | |||
488 | } | |||
489 | ||||
490 | inline Node* BaseCountedLoopNode::init_trip() const { | |||
491 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
492 | return cle != NULL__null ? cle->init_trip() : NULL__null; | |||
493 | } | |||
494 | inline Node* BaseCountedLoopNode::stride() const { | |||
495 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
496 | return cle != NULL__null ? cle->stride() : NULL__null; | |||
497 | } | |||
498 | ||||
499 | inline bool BaseCountedLoopNode::stride_is_con() const { | |||
500 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
501 | return cle != NULL__null && cle->stride_is_con(); | |||
502 | } | |||
503 | inline Node* BaseCountedLoopNode::limit() const { | |||
504 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
505 | return cle != NULL__null ? cle->limit() : NULL__null; | |||
506 | } | |||
507 | inline Node* BaseCountedLoopNode::incr() const { | |||
508 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
509 | return cle != NULL__null ? cle->incr() : NULL__null; | |||
510 | } | |||
511 | inline Node* BaseCountedLoopNode::phi() const { | |||
512 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
513 | return cle != NULL__null ? cle->phi() : NULL__null; | |||
514 | } | |||
515 | ||||
516 | inline jlong BaseCountedLoopNode::stride_con() const { | |||
517 | BaseCountedLoopEndNode* cle = loopexit_or_null(); | |||
518 | return cle != NULL__null ? cle->stride_con() : 0; | |||
519 | } | |||
520 | ||||
521 | ||||
522 | //------------------------------LoopLimitNode----------------------------- | |||
523 | // Counted Loop limit node which represents exact final iterator value: | |||
524 | // trip_count = (limit - init_trip + stride - 1)/stride | |||
525 | // final_value= trip_count * stride + init_trip. | |||
526 | // Use HW instructions to calculate it when it can overflow in integer. | |||
527 | // Note, final_value should fit into integer since counted loop has | |||
528 | // limit check: limit <= max_int-stride. | |||
529 | class LoopLimitNode : public Node { | |||
530 | enum { Init=1, Limit=2, Stride=3 }; | |||
531 | public: | |||
532 | LoopLimitNode( Compile* C, Node *init, Node *limit, Node *stride ) : Node(0,init,limit,stride) { | |||
533 | // Put it on the Macro nodes list to optimize during macro nodes expansion. | |||
534 | init_flags(Flag_is_macro); | |||
535 | C->add_macro_node(this); | |||
536 | } | |||
537 | virtual int Opcode() const; | |||
538 | virtual const Type *bottom_type() const { return TypeInt::INT; } | |||
539 | virtual uint ideal_reg() const { return Op_RegI; } | |||
540 | virtual const Type* Value(PhaseGVN* phase) const; | |||
541 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |||
542 | virtual Node* Identity(PhaseGVN* phase); | |||
543 | }; | |||
544 | ||||
545 | // Support for strip mining | |||
546 | class OuterStripMinedLoopNode : public LoopNode { | |||
547 | private: | |||
548 | CountedLoopNode* inner_loop() const; | |||
549 | public: | |||
550 | OuterStripMinedLoopNode(Compile* C, Node *entry, Node *backedge) | |||
551 | : LoopNode(entry, backedge) { | |||
552 | init_class_id(Class_OuterStripMinedLoop); | |||
553 | init_flags(Flag_is_macro); | |||
554 | C->add_macro_node(this); | |||
555 | } | |||
556 | ||||
557 | virtual int Opcode() const; | |||
558 | ||||
559 | virtual IfTrueNode* outer_loop_tail() const; | |||
560 | virtual OuterStripMinedLoopEndNode* outer_loop_end() const; | |||
561 | virtual IfFalseNode* outer_loop_exit() const; | |||
562 | virtual SafePointNode* outer_safepoint() const; | |||
563 | void adjust_strip_mined_loop(PhaseIterGVN* igvn); | |||
564 | }; | |||
565 | ||||
566 | class OuterStripMinedLoopEndNode : public IfNode { | |||
567 | public: | |||
568 | OuterStripMinedLoopEndNode(Node *control, Node *test, float prob, float cnt) | |||
569 | : IfNode(control, test, prob, cnt) { | |||
570 | init_class_id(Class_OuterStripMinedLoopEnd); | |||
571 | } | |||
572 | ||||
573 | virtual int Opcode() const; | |||
574 | ||||
575 | virtual const Type* Value(PhaseGVN* phase) const; | |||
576 | virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); | |||
577 | ||||
578 | bool is_expanded(PhaseGVN *phase) const; | |||
579 | }; | |||
580 | ||||
581 | // -----------------------------IdealLoopTree---------------------------------- | |||
582 | class IdealLoopTree : public ResourceObj { | |||
583 | public: | |||
584 | IdealLoopTree *_parent; // Parent in loop tree | |||
585 | IdealLoopTree *_next; // Next sibling in loop tree | |||
586 | IdealLoopTree *_child; // First child in loop tree | |||
587 | ||||
588 | // The head-tail backedge defines the loop. | |||
589 | // If a loop has multiple backedges, this is addressed during cleanup where | |||
590 | // we peel off the multiple backedges, merging all edges at the bottom and | |||
591 | // ensuring that one proper backedge flow into the loop. | |||
592 | Node *_head; // Head of loop | |||
593 | Node *_tail; // Tail of loop | |||
594 | inline Node *tail(); // Handle lazy update of _tail field | |||
595 | inline Node *head(); // Handle lazy update of _head field | |||
596 | PhaseIdealLoop* _phase; | |||
597 | int _local_loop_unroll_limit; | |||
598 | int _local_loop_unroll_factor; | |||
599 | ||||
600 | Node_List _body; // Loop body for inner loops | |||
601 | ||||
602 | uint16_t _nest; // Nesting depth | |||
603 | uint8_t _irreducible:1, // True if irreducible | |||
604 | _has_call:1, // True if has call safepoint | |||
605 | _has_sfpt:1, // True if has non-call safepoint | |||
606 | _rce_candidate:1; // True if candidate for range check elimination | |||
607 | ||||
608 | Node_List* _safepts; // List of safepoints in this loop | |||
609 | Node_List* _required_safept; // A inner loop cannot delete these safepts; | |||
610 | bool _allow_optimizations; // Allow loop optimizations | |||
611 | ||||
612 | IdealLoopTree( PhaseIdealLoop* phase, Node *head, Node *tail ) | |||
613 | : _parent(0), _next(0), _child(0), | |||
614 | _head(head), _tail(tail), | |||
615 | _phase(phase), | |||
616 | _local_loop_unroll_limit(0), _local_loop_unroll_factor(0), | |||
617 | _nest(0), _irreducible(0), _has_call(0), _has_sfpt(0), _rce_candidate(0), | |||
618 | _safepts(NULL__null), | |||
619 | _required_safept(NULL__null), | |||
620 | _allow_optimizations(true) | |||
621 | { | |||
622 | precond(_head != NULL)do { if (!(_head != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 622, "assert(" "_head != __null" ") failed", "precond"); :: breakpoint(); } } while (0); | |||
623 | precond(_tail != NULL)do { if (!(_tail != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 623, "assert(" "_tail != __null" ") failed", "precond"); :: breakpoint(); } } while (0); | |||
624 | } | |||
625 | ||||
626 | // Is 'l' a member of 'this'? | |||
627 | bool is_member(const IdealLoopTree *l) const; // Test for nested membership | |||
628 | ||||
629 | // Set loop nesting depth. Accumulate has_call bits. | |||
630 | int set_nest( uint depth ); | |||
631 | ||||
632 | // Split out multiple fall-in edges from the loop header. Move them to a | |||
633 | // private RegionNode before the loop. This becomes the loop landing pad. | |||
634 | void split_fall_in( PhaseIdealLoop *phase, int fall_in_cnt ); | |||
635 | ||||
636 | // Split out the outermost loop from this shared header. | |||
637 | void split_outer_loop( PhaseIdealLoop *phase ); | |||
638 | ||||
639 | // Merge all the backedges from the shared header into a private Region. | |||
640 | // Feed that region as the one backedge to this loop. | |||
641 | void merge_many_backedges( PhaseIdealLoop *phase ); | |||
642 | ||||
643 | // Split shared headers and insert loop landing pads. | |||
644 | // Insert a LoopNode to replace the RegionNode. | |||
645 | // Returns TRUE if loop tree is structurally changed. | |||
646 | bool beautify_loops( PhaseIdealLoop *phase ); | |||
647 | ||||
648 | // Perform optimization to use the loop predicates for null checks and range checks. | |||
649 | // Applies to any loop level (not just the innermost one) | |||
650 | bool loop_predication( PhaseIdealLoop *phase); | |||
651 | ||||
652 | // Perform iteration-splitting on inner loops. Split iterations to | |||
653 | // avoid range checks or one-shot null checks. Returns false if the | |||
654 | // current round of loop opts should stop. | |||
655 | bool iteration_split( PhaseIdealLoop *phase, Node_List &old_new ); | |||
656 | ||||
657 | // Driver for various flavors of iteration splitting. Returns false | |||
658 | // if the current round of loop opts should stop. | |||
659 | bool iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_new ); | |||
660 | ||||
661 | // Given dominators, try to find loops with calls that must always be | |||
662 | // executed (call dominates loop tail). These loops do not need non-call | |||
663 | // safepoints (ncsfpt). | |||
664 | void check_safepts(VectorSet &visited, Node_List &stack); | |||
665 | ||||
666 | // Allpaths backwards scan from loop tail, terminating each path at first safepoint | |||
667 | // encountered. | |||
668 | void allpaths_check_safepts(VectorSet &visited, Node_List &stack); | |||
669 | ||||
670 | // Remove safepoints from loop. Optionally keeping one. | |||
671 | void remove_safepoints(PhaseIdealLoop* phase, bool keep_one); | |||
672 | ||||
673 | // Convert to counted loops where possible | |||
674 | void counted_loop( PhaseIdealLoop *phase ); | |||
675 | ||||
676 | // Check for Node being a loop-breaking test | |||
677 | Node *is_loop_exit(Node *iff) const; | |||
678 | ||||
679 | // Remove simplistic dead code from loop body | |||
680 | void DCE_loop_body(); | |||
681 | ||||
682 | // Look for loop-exit tests with my 50/50 guesses from the Parsing stage. | |||
683 | // Replace with a 1-in-10 exit guess. | |||
684 | void adjust_loop_exit_prob( PhaseIdealLoop *phase ); | |||
685 | ||||
686 | // Return TRUE or FALSE if the loop should never be RCE'd or aligned. | |||
687 | // Useful for unrolling loops with NO array accesses. | |||
688 | bool policy_peel_only( PhaseIdealLoop *phase ) const; | |||
689 | ||||
690 | // Return TRUE or FALSE if the loop should be unswitched -- clone | |||
691 | // loop with an invariant test | |||
692 | bool policy_unswitching( PhaseIdealLoop *phase ) const; | |||
693 | ||||
694 | // Micro-benchmark spamming. Remove empty loops. | |||
695 | bool do_remove_empty_loop( PhaseIdealLoop *phase ); | |||
696 | ||||
697 | // Convert one iteration loop into normal code. | |||
698 | bool do_one_iteration_loop( PhaseIdealLoop *phase ); | |||
699 | ||||
700 | // Return TRUE or FALSE if the loop should be peeled or not. Peel if we can | |||
701 | // move some loop-invariant test (usually a null-check) before the loop. | |||
702 | bool policy_peeling(PhaseIdealLoop *phase); | |||
703 | ||||
704 | uint estimate_peeling(PhaseIdealLoop *phase); | |||
705 | ||||
706 | // Return TRUE or FALSE if the loop should be maximally unrolled. Stash any | |||
707 | // known trip count in the counted loop node. | |||
708 | bool policy_maximally_unroll(PhaseIdealLoop *phase) const; | |||
709 | ||||
710 | // Return TRUE or FALSE if the loop should be unrolled or not. Apply unroll | |||
711 | // if the loop is a counted loop and the loop body is small enough. | |||
712 | bool policy_unroll(PhaseIdealLoop *phase); | |||
713 | ||||
714 | // Loop analyses to map to a maximal superword unrolling for vectorization. | |||
715 | void policy_unroll_slp_analysis(CountedLoopNode *cl, PhaseIdealLoop *phase, int future_unroll_ct); | |||
716 | ||||
717 | // Return TRUE or FALSE if the loop should be range-check-eliminated. | |||
718 | // Gather a list of IF tests that are dominated by iteration splitting; | |||
719 | // also gather the end of the first split and the start of the 2nd split. | |||
720 | bool policy_range_check(PhaseIdealLoop* phase, bool provisional, BasicType bt) const; | |||
721 | ||||
722 | // Return TRUE if "iff" is a range check. | |||
723 | bool is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar DEBUG_ONLY(COMMA ProjNode *predicate_proj), ProjNode *predicate_proj) const; | |||
724 | bool is_range_check_if(IfNode* iff, PhaseIdealLoop* phase, BasicType bt, Node* iv, Node*& range, Node*& offset, | |||
725 | jlong& scale) const; | |||
726 | ||||
727 | // Estimate the number of nodes required when cloning a loop (body). | |||
728 | uint est_loop_clone_sz(uint factor) const; | |||
729 | // Estimate the number of nodes required when unrolling a loop (body). | |||
730 | uint est_loop_unroll_sz(uint factor) const; | |||
731 | ||||
732 | // Compute loop trip count if possible | |||
733 | void compute_trip_count(PhaseIdealLoop* phase); | |||
734 | ||||
735 | // Compute loop trip count from profile data | |||
736 | float compute_profile_trip_cnt_helper(Node* n); | |||
737 | void compute_profile_trip_cnt( PhaseIdealLoop *phase ); | |||
738 | ||||
739 | // Reassociate invariant expressions. | |||
740 | void reassociate_invariants(PhaseIdealLoop *phase); | |||
741 | // Reassociate invariant binary expressions. | |||
742 | Node* reassociate(Node* n1, PhaseIdealLoop *phase); | |||
743 | // Reassociate invariant add and subtract expressions. | |||
744 | Node* reassociate_add_sub(Node* n1, int inv1_idx, int inv2_idx, PhaseIdealLoop *phase); | |||
745 | // Return nonzero index of invariant operand if invariant and variant | |||
746 | // are combined with an associative binary. Helper for reassociate_invariants. | |||
747 | int find_invariant(Node* n, PhaseIdealLoop *phase); | |||
748 | // Return TRUE if "n" is associative. | |||
749 | bool is_associative(Node* n, Node* base=NULL__null); | |||
750 | ||||
751 | // Return true if n is invariant | |||
752 | bool is_invariant(Node* n) const; | |||
753 | ||||
754 | // Put loop body on igvn work list | |||
755 | void record_for_igvn(); | |||
756 | ||||
757 | bool is_root() { return _parent == NULL__null; } | |||
758 | // A proper/reducible loop w/o any (occasional) dead back-edge. | |||
759 | bool is_loop() { return !_irreducible && !tail()->is_top(); } | |||
760 | bool is_counted() { return is_loop() && _head->is_CountedLoop(); } | |||
761 | bool is_innermost() { return is_loop() && _child == NULL__null; } | |||
762 | ||||
763 | void remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop *phase); | |||
764 | ||||
765 | #ifndef PRODUCT | |||
766 | void dump_head() const; // Dump loop head only | |||
767 | void dump() const; // Dump this loop recursively | |||
768 | void verify_tree(IdealLoopTree *loop, const IdealLoopTree *parent) const; | |||
769 | #endif | |||
770 | ||||
771 | private: | |||
772 | enum { EMPTY_LOOP_SIZE = 7 }; // Number of nodes in an empty loop. | |||
773 | ||||
774 | // Estimate the number of nodes resulting from control and data flow merge. | |||
775 | uint est_loop_flow_merge_sz() const; | |||
776 | }; | |||
777 | ||||
778 | // -----------------------------PhaseIdealLoop--------------------------------- | |||
779 | // Computes the mapping from Nodes to IdealLoopTrees. Organizes IdealLoopTrees | |||
780 | // into a loop tree. Drives the loop-based transformations on the ideal graph. | |||
781 | class PhaseIdealLoop : public PhaseTransform { | |||
782 | friend class IdealLoopTree; | |||
783 | friend class SuperWord; | |||
784 | friend class CountedLoopReserveKit; | |||
785 | friend class ShenandoahBarrierC2Support; | |||
786 | friend class AutoNodeBudget; | |||
787 | ||||
788 | // Pre-computed def-use info | |||
789 | PhaseIterGVN &_igvn; | |||
790 | ||||
791 | // Head of loop tree | |||
792 | IdealLoopTree* _ltree_root; | |||
793 | ||||
794 | // Array of pre-order numbers, plus post-visited bit. | |||
795 | // ZERO for not pre-visited. EVEN for pre-visited but not post-visited. | |||
796 | // ODD for post-visited. Other bits are the pre-order number. | |||
797 | uint *_preorders; | |||
798 | uint _max_preorder; | |||
799 | ||||
800 | const PhaseIdealLoop* _verify_me; | |||
801 | bool _verify_only; | |||
802 | ||||
803 | // Allocate _preorders[] array | |||
804 | void allocate_preorders() { | |||
805 | _max_preorder = C->unique()+8; | |||
806 | _preorders = NEW_RESOURCE_ARRAY(uint, _max_preorder)(uint*) resource_allocate_bytes((_max_preorder) * sizeof(uint )); | |||
807 | memset(_preorders, 0, sizeof(uint) * _max_preorder); | |||
808 | } | |||
809 | ||||
810 | // Allocate _preorders[] array | |||
811 | void reallocate_preorders() { | |||
812 | if ( _max_preorder < C->unique() ) { | |||
813 | _preorders = REALLOC_RESOURCE_ARRAY(uint, _preorders, _max_preorder, C->unique())(uint*) resource_reallocate_bytes((char*)(_preorders), (_max_preorder ) * sizeof(uint), (C->unique()) * sizeof(uint)); | |||
814 | _max_preorder = C->unique(); | |||
815 | } | |||
816 | memset(_preorders, 0, sizeof(uint) * _max_preorder); | |||
817 | } | |||
818 | ||||
819 | // Check to grow _preorders[] array for the case when build_loop_tree_impl() | |||
820 | // adds new nodes. | |||
821 | void check_grow_preorders( ) { | |||
822 | if ( _max_preorder < C->unique() ) { | |||
823 | uint newsize = _max_preorder<<1; // double size of array | |||
824 | _preorders = REALLOC_RESOURCE_ARRAY(uint, _preorders, _max_preorder, newsize)(uint*) resource_reallocate_bytes((char*)(_preorders), (_max_preorder ) * sizeof(uint), (newsize) * sizeof(uint)); | |||
825 | memset(&_preorders[_max_preorder],0,sizeof(uint)*(newsize-_max_preorder)); | |||
826 | _max_preorder = newsize; | |||
827 | } | |||
828 | } | |||
829 | // Check for pre-visited. Zero for NOT visited; non-zero for visited. | |||
830 | int is_visited( Node *n ) const { return _preorders[n->_idx]; } | |||
831 | // Pre-order numbers are written to the Nodes array as low-bit-set values. | |||
832 | void set_preorder_visited( Node *n, int pre_order ) { | |||
833 | assert( !is_visited( n ), "already set" )do { if (!(!is_visited( n ))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 833, "assert(" "!is_visited( n )" ") failed", "already set" ); ::breakpoint(); } } while (0); | |||
834 | _preorders[n->_idx] = (pre_order<<1); | |||
835 | }; | |||
836 | // Return pre-order number. | |||
837 | int get_preorder( Node *n ) const { assert( is_visited(n), "" )do { if (!(is_visited(n))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 837, "assert(" "is_visited(n)" ") failed", ""); ::breakpoint (); } } while (0); return _preorders[n->_idx]>>1; } | |||
838 | ||||
839 | // Check for being post-visited. | |||
840 | // Should be previsited already (checked with assert(is_visited(n))). | |||
841 | int is_postvisited( Node *n ) const { assert( is_visited(n), "" )do { if (!(is_visited(n))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 841, "assert(" "is_visited(n)" ") failed", ""); ::breakpoint (); } } while (0); return _preorders[n->_idx]&1; } | |||
842 | ||||
843 | // Mark as post visited | |||
844 | void set_postvisited( Node *n ) { assert( !is_postvisited( n ), "" )do { if (!(!is_postvisited( n ))) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 844, "assert(" "!is_postvisited( n )" ") failed", ""); ::breakpoint (); } } while (0); _preorders[n->_idx] |= 1; } | |||
845 | ||||
846 | public: | |||
847 | // Set/get control node out. Set lower bit to distinguish from IdealLoopTree | |||
848 | // Returns true if "n" is a data node, false if it's a control node. | |||
849 | bool has_ctrl( Node *n ) const { return ((intptr_t)_nodes[n->_idx]) & 1; } | |||
850 | ||||
851 | private: | |||
852 | // clear out dead code after build_loop_late | |||
853 | Node_List _deadlist; | |||
854 | ||||
855 | // Support for faster execution of get_late_ctrl()/dom_lca() | |||
856 | // when a node has many uses and dominator depth is deep. | |||
857 | GrowableArray<jlong> _dom_lca_tags; | |||
858 | uint _dom_lca_tags_round; | |||
859 | void init_dom_lca_tags(); | |||
860 | ||||
861 | // Helper for debugging bad dominance relationships | |||
862 | bool verify_dominance(Node* n, Node* use, Node* LCA, Node* early); | |||
863 | ||||
864 | Node* compute_lca_of_uses(Node* n, Node* early, bool verify = false); | |||
865 | ||||
866 | // Inline wrapper for frequent cases: | |||
867 | // 1) only one use | |||
868 | // 2) a use is the same as the current LCA passed as 'n1' | |||
869 | Node *dom_lca_for_get_late_ctrl( Node *lca, Node *n, Node *tag ) { | |||
870 | assert( n->is_CFG(), "" )do { if (!(n->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 870, "assert(" "n->is_CFG()" ") failed", ""); ::breakpoint (); } } while (0); | |||
871 | // Fast-path NULL lca | |||
872 | if( lca != NULL__null && lca != n ) { | |||
873 | assert( lca->is_CFG(), "" )do { if (!(lca->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 873, "assert(" "lca->is_CFG()" ") failed", ""); ::breakpoint (); } } while (0); | |||
874 | // find LCA of all uses | |||
875 | n = dom_lca_for_get_late_ctrl_internal( lca, n, tag ); | |||
876 | } | |||
877 | return find_non_split_ctrl(n); | |||
878 | } | |||
879 | Node *dom_lca_for_get_late_ctrl_internal( Node *lca, Node *n, Node *tag ); | |||
880 | ||||
881 | // Helper function for directing control inputs away from CFG split points. | |||
882 | Node *find_non_split_ctrl( Node *ctrl ) const { | |||
883 | if (ctrl != NULL__null) { | |||
884 | if (ctrl->is_MultiBranch()) { | |||
885 | ctrl = ctrl->in(0); | |||
886 | } | |||
887 | assert(ctrl->is_CFG(), "CFG")do { if (!(ctrl->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 887, "assert(" "ctrl->is_CFG()" ") failed", "CFG"); ::breakpoint (); } } while (0); | |||
888 | } | |||
889 | return ctrl; | |||
890 | } | |||
891 | ||||
892 | Node* cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop); | |||
893 | ||||
894 | #ifdef ASSERT1 | |||
895 | void ensure_zero_trip_guard_proj(Node* node, bool is_main_loop); | |||
896 | #endif | |||
897 | void copy_skeleton_predicates_to_main_loop_helper(Node* predicate, Node* init, Node* stride, IdealLoopTree* outer_loop, LoopNode* outer_main_head, | |||
898 | uint dd_main_head, const uint idx_before_pre_post, const uint idx_after_post_before_pre, | |||
899 | Node* zero_trip_guard_proj_main, Node* zero_trip_guard_proj_post, const Node_List &old_new); | |||
900 | void copy_skeleton_predicates_to_main_loop(CountedLoopNode* pre_head, Node* init, Node* stride, IdealLoopTree* outer_loop, LoopNode* outer_main_head, | |||
901 | uint dd_main_head, const uint idx_before_pre_post, const uint idx_after_post_before_pre, | |||
902 | Node* zero_trip_guard_proj_main, Node* zero_trip_guard_proj_post, const Node_List &old_new); | |||
903 | Node* clone_skeleton_predicate_for_main_or_post_loop(Node* iff, Node* new_init, Node* new_stride, Node* predicate, Node* uncommon_proj, Node* control, | |||
904 | IdealLoopTree* outer_loop, Node* input_proj); | |||
905 | Node* clone_skeleton_predicate_bool(Node* iff, Node* new_init, Node* new_stride, Node* control); | |||
906 | static bool skeleton_predicate_has_opaque(IfNode* iff); | |||
907 | static void get_skeleton_predicates(Node* predicate, Unique_Node_List& list, bool get_opaque = false); | |||
908 | void update_main_loop_skeleton_predicates(Node* ctrl, CountedLoopNode* loop_head, Node* init, int stride_con); | |||
909 | void copy_skeleton_predicates_to_post_loop(LoopNode* main_loop_head, CountedLoopNode* post_loop_head, Node* init, Node* stride); | |||
910 | void insert_loop_limit_check(ProjNode* limit_check_proj, Node* cmp_limit, Node* bol); | |||
911 | #ifdef ASSERT1 | |||
912 | bool only_has_infinite_loops(); | |||
913 | #endif | |||
914 | ||||
915 | void log_loop_tree(); | |||
916 | ||||
917 | public: | |||
918 | ||||
919 | PhaseIterGVN &igvn() const { return _igvn; } | |||
920 | ||||
921 | bool has_node( Node* n ) const { | |||
922 | guarantee(n != NULL, "No Node.")do { if (!(n != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 922, "guarantee(" "n != NULL" ") failed", "No Node."); ::breakpoint (); } } while (0); | |||
923 | return _nodes[n->_idx] != NULL__null; | |||
924 | } | |||
925 | // check if transform created new nodes that need _ctrl recorded | |||
926 | Node *get_late_ctrl( Node *n, Node *early ); | |||
927 | Node *get_early_ctrl( Node *n ); | |||
928 | Node *get_early_ctrl_for_expensive(Node *n, Node* earliest); | |||
929 | void set_early_ctrl(Node* n, bool update_body); | |||
930 | void set_subtree_ctrl(Node* n, bool update_body); | |||
931 | void set_ctrl( Node *n, Node *ctrl ) { | |||
932 | assert( !has_node(n) || has_ctrl(n), "" )do { if (!(!has_node(n) || has_ctrl(n))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 932, "assert(" "!has_node(n) || has_ctrl(n)" ") failed", "" ); ::breakpoint(); } } while (0); | |||
933 | assert( ctrl->in(0), "cannot set dead control node" )do { if (!(ctrl->in(0))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 933, "assert(" "ctrl->in(0)" ") failed", "cannot set dead control node" ); ::breakpoint(); } } while (0); | |||
| ||||
934 | assert( ctrl == find_non_split_ctrl(ctrl), "must set legal crtl" )do { if (!(ctrl == find_non_split_ctrl(ctrl))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 934, "assert(" "ctrl == find_non_split_ctrl(ctrl)" ") failed" , "must set legal crtl"); ::breakpoint(); } } while (0); | |||
935 | _nodes.map( n->_idx, (Node*)((intptr_t)ctrl + 1) ); | |||
936 | } | |||
937 | // Set control and update loop membership | |||
938 | void set_ctrl_and_loop(Node* n, Node* ctrl) { | |||
939 | IdealLoopTree* old_loop = get_loop(get_ctrl(n)); | |||
940 | IdealLoopTree* new_loop = get_loop(ctrl); | |||
941 | if (old_loop != new_loop) { | |||
942 | if (old_loop->_child == NULL__null) old_loop->_body.yank(n); | |||
943 | if (new_loop->_child == NULL__null) new_loop->_body.push(n); | |||
944 | } | |||
945 | set_ctrl(n, ctrl); | |||
946 | } | |||
947 | // Control nodes can be replaced or subsumed. During this pass they | |||
948 | // get their replacement Node in slot 1. Instead of updating the block | |||
949 | // location of all Nodes in the subsumed block, we lazily do it. As we | |||
950 | // pull such a subsumed block out of the array, we write back the final | |||
951 | // correct block. | |||
952 | Node *get_ctrl( Node *i ) { | |||
953 | ||||
954 | assert(has_node(i), "")do { if (!(has_node(i))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 954, "assert(" "has_node(i)" ") failed", ""); ::breakpoint( ); } } while (0); | |||
955 | Node *n = get_ctrl_no_update(i); | |||
956 | _nodes.map( i->_idx, (Node*)((intptr_t)n + 1) ); | |||
957 | assert(has_node(i) && has_ctrl(i), "")do { if (!(has_node(i) && has_ctrl(i))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 957, "assert(" "has_node(i) && has_ctrl(i)" ") failed" , ""); ::breakpoint(); } } while (0); | |||
958 | assert(n == find_non_split_ctrl(n), "must return legal ctrl" )do { if (!(n == find_non_split_ctrl(n))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 958, "assert(" "n == find_non_split_ctrl(n)" ") failed", "must return legal ctrl" ); ::breakpoint(); } } while (0); | |||
959 | return n; | |||
960 | } | |||
961 | // true if CFG node d dominates CFG node n | |||
962 | bool is_dominator(Node *d, Node *n); | |||
963 | // return get_ctrl for a data node and self(n) for a CFG node | |||
964 | Node* ctrl_or_self(Node* n) { | |||
965 | if (has_ctrl(n)) | |||
966 | return get_ctrl(n); | |||
967 | else { | |||
968 | assert (n->is_CFG(), "must be a CFG node")do { if (!(n->is_CFG())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 968, "assert(" "n->is_CFG()" ") failed", "must be a CFG node" ); ::breakpoint(); } } while (0); | |||
969 | return n; | |||
970 | } | |||
971 | } | |||
972 | ||||
973 | Node *get_ctrl_no_update_helper(Node *i) const { | |||
974 | assert(has_ctrl(i), "should be control, not loop")do { if (!(has_ctrl(i))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 974, "assert(" "has_ctrl(i)" ") failed", "should be control, not loop" ); ::breakpoint(); } } while (0); | |||
975 | return (Node*)(((intptr_t)_nodes[i->_idx]) & ~1); | |||
976 | } | |||
977 | ||||
978 | Node *get_ctrl_no_update(Node *i) const { | |||
979 | assert( has_ctrl(i), "" )do { if (!(has_ctrl(i))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 979, "assert(" "has_ctrl(i)" ") failed", ""); ::breakpoint( ); } } while (0); | |||
980 | Node *n = get_ctrl_no_update_helper(i); | |||
981 | if (!n->in(0)) { | |||
982 | // Skip dead CFG nodes | |||
983 | do { | |||
984 | n = get_ctrl_no_update_helper(n); | |||
985 | } while (!n->in(0)); | |||
986 | n = find_non_split_ctrl(n); | |||
987 | } | |||
988 | return n; | |||
989 | } | |||
990 | ||||
991 | // Check for loop being set | |||
992 | // "n" must be a control node. Returns true if "n" is known to be in a loop. | |||
993 | bool has_loop( Node *n ) const { | |||
994 | assert(!has_node(n) || !has_ctrl(n), "")do { if (!(!has_node(n) || !has_ctrl(n))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 994, "assert(" "!has_node(n) || !has_ctrl(n)" ") failed", "" ); ::breakpoint(); } } while (0); | |||
995 | return has_node(n); | |||
996 | } | |||
997 | // Set loop | |||
998 | void set_loop( Node *n, IdealLoopTree *loop ) { | |||
999 | _nodes.map(n->_idx, (Node*)loop); | |||
1000 | } | |||
1001 | // Lazy-dazy update of 'get_ctrl' and 'idom_at' mechanisms. Replace | |||
1002 | // the 'old_node' with 'new_node'. Kill old-node. Add a reference | |||
1003 | // from old_node to new_node to support the lazy update. Reference | |||
1004 | // replaces loop reference, since that is not needed for dead node. | |||
1005 | void lazy_update(Node *old_node, Node *new_node) { | |||
1006 | assert(old_node != new_node, "no cycles please")do { if (!(old_node != new_node)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1006, "assert(" "old_node != new_node" ") failed", "no cycles please" ); ::breakpoint(); } } while (0); | |||
1007 | // Re-use the side array slot for this node to provide the | |||
1008 | // forwarding pointer. | |||
1009 | _nodes.map(old_node->_idx, (Node*)((intptr_t)new_node + 1)); | |||
1010 | } | |||
1011 | void lazy_replace(Node *old_node, Node *new_node) { | |||
1012 | _igvn.replace_node(old_node, new_node); | |||
1013 | lazy_update(old_node, new_node); | |||
1014 | } | |||
1015 | ||||
1016 | private: | |||
1017 | ||||
1018 | // Place 'n' in some loop nest, where 'n' is a CFG node | |||
1019 | void build_loop_tree(); | |||
1020 | int build_loop_tree_impl( Node *n, int pre_order ); | |||
1021 | // Insert loop into the existing loop tree. 'innermost' is a leaf of the | |||
1022 | // loop tree, not the root. | |||
1023 | IdealLoopTree *sort( IdealLoopTree *loop, IdealLoopTree *innermost ); | |||
1024 | ||||
1025 | // Place Data nodes in some loop nest | |||
1026 | void build_loop_early( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ); | |||
1027 | void build_loop_late ( VectorSet &visited, Node_List &worklist, Node_Stack &nstack ); | |||
1028 | void build_loop_late_post_work(Node* n, bool pinned); | |||
1029 | void build_loop_late_post(Node* n); | |||
1030 | void verify_strip_mined_scheduling(Node *n, Node* least); | |||
1031 | ||||
1032 | // Array of immediate dominance info for each CFG node indexed by node idx | |||
1033 | private: | |||
1034 | uint _idom_size; | |||
1035 | Node **_idom; // Array of immediate dominators | |||
1036 | uint *_dom_depth; // Used for fast LCA test | |||
1037 | GrowableArray<uint>* _dom_stk; // For recomputation of dom depth | |||
1038 | ||||
1039 | // build the loop tree and perform any requested optimizations | |||
1040 | void build_and_optimize(LoopOptsMode mode); | |||
1041 | ||||
1042 | // Dominators for the sea of nodes | |||
1043 | void Dominators(); | |||
1044 | ||||
1045 | // Compute the Ideal Node to Loop mapping | |||
1046 | PhaseIdealLoop(PhaseIterGVN& igvn, LoopOptsMode mode) : | |||
1047 | PhaseTransform(Ideal_Loop), | |||
1048 | _igvn(igvn), | |||
1049 | _verify_me(nullptr), | |||
1050 | _verify_only(false), | |||
1051 | _nodes_required(UINT_MAX(2147483647 *2U +1U)) { | |||
1052 | assert(mode != LoopOptsVerify, "wrong constructor to verify IdealLoop")do { if (!(mode != LoopOptsVerify)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1052, "assert(" "mode != LoopOptsVerify" ") failed", "wrong constructor to verify IdealLoop" ); ::breakpoint(); } } while (0); | |||
1053 | build_and_optimize(mode); | |||
1054 | } | |||
1055 | ||||
1056 | #ifndef PRODUCT | |||
1057 | // Verify that verify_me made the same decisions as a fresh run | |||
1058 | // or only verify that the graph is valid if verify_me is null. | |||
1059 | PhaseIdealLoop(PhaseIterGVN& igvn, const PhaseIdealLoop* verify_me = nullptr) : | |||
1060 | PhaseTransform(Ideal_Loop), | |||
1061 | _igvn(igvn), | |||
1062 | _verify_me(verify_me), | |||
1063 | _verify_only(verify_me == nullptr), | |||
1064 | _nodes_required(UINT_MAX(2147483647 *2U +1U)) { | |||
1065 | build_and_optimize(LoopOptsVerify); | |||
1066 | } | |||
1067 | #endif | |||
1068 | ||||
1069 | public: | |||
1070 | Node* idom_no_update(Node* d) const { | |||
1071 | return idom_no_update(d->_idx); | |||
1072 | } | |||
1073 | ||||
1074 | Node* idom_no_update(uint didx) const { | |||
1075 | assert(didx < _idom_size, "oob")do { if (!(didx < _idom_size)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1075, "assert(" "didx < _idom_size" ") failed", "oob"); :: breakpoint(); } } while (0); | |||
1076 | Node* n = _idom[didx]; | |||
1077 | assert(n != NULL,"Bad immediate dominator info.")do { if (!(n != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1077, "assert(" "n != __null" ") failed", "Bad immediate dominator info." ); ::breakpoint(); } } while (0); | |||
1078 | while (n->in(0) == NULL__null) { // Skip dead CFG nodes | |||
1079 | n = (Node*)(((intptr_t)_nodes[n->_idx]) & ~1); | |||
1080 | assert(n != NULL,"Bad immediate dominator info.")do { if (!(n != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1080, "assert(" "n != __null" ") failed", "Bad immediate dominator info." ); ::breakpoint(); } } while (0); | |||
1081 | } | |||
1082 | return n; | |||
1083 | } | |||
1084 | ||||
1085 | Node *idom(Node* d) const { | |||
1086 | return idom(d->_idx); | |||
1087 | } | |||
1088 | ||||
1089 | Node *idom(uint didx) const { | |||
1090 | Node *n = idom_no_update(didx); | |||
1091 | _idom[didx] = n; // Lazily remove dead CFG nodes from table. | |||
1092 | return n; | |||
1093 | } | |||
1094 | ||||
1095 | uint dom_depth(Node* d) const { | |||
1096 | guarantee(d != NULL, "Null dominator info.")do { if (!(d != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1096, "guarantee(" "d != NULL" ") failed", "Null dominator info." ); ::breakpoint(); } } while (0); | |||
1097 | guarantee(d->_idx < _idom_size, "")do { if (!(d->_idx < _idom_size)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1097, "guarantee(" "d->_idx < _idom_size" ") failed", ""); ::breakpoint(); } } while (0); | |||
1098 | return _dom_depth[d->_idx]; | |||
1099 | } | |||
1100 | void set_idom(Node* d, Node* n, uint dom_depth); | |||
1101 | // Locally compute IDOM using dom_lca call | |||
1102 | Node *compute_idom( Node *region ) const; | |||
1103 | // Recompute dom_depth | |||
1104 | void recompute_dom_depth(); | |||
1105 | ||||
1106 | // Is safept not required by an outer loop? | |||
1107 | bool is_deleteable_safept(Node* sfpt); | |||
1108 | ||||
1109 | // Replace parallel induction variable (parallel to trip counter) | |||
1110 | void replace_parallel_iv(IdealLoopTree *loop); | |||
1111 | ||||
1112 | Node *dom_lca( Node *n1, Node *n2 ) const { | |||
1113 | return find_non_split_ctrl(dom_lca_internal(n1, n2)); | |||
1114 | } | |||
1115 | Node *dom_lca_internal( Node *n1, Node *n2 ) const; | |||
1116 | ||||
1117 | // Build and verify the loop tree without modifying the graph. This | |||
1118 | // is useful to verify that all inputs properly dominate their uses. | |||
1119 | static void verify(PhaseIterGVN& igvn) { | |||
1120 | #ifdef ASSERT1 | |||
1121 | ResourceMark rm; | |||
1122 | Compile::TracePhase tp("idealLoopVerify", &timers[_t_idealLoopVerify]); | |||
1123 | PhaseIdealLoop v(igvn); | |||
1124 | #endif | |||
1125 | } | |||
1126 | ||||
1127 | // Recommended way to use PhaseIdealLoop. | |||
1128 | // Run PhaseIdealLoop in some mode and allocates a local scope for memory allocations. | |||
1129 | static void optimize(PhaseIterGVN &igvn, LoopOptsMode mode) { | |||
1130 | ResourceMark rm; | |||
1131 | PhaseIdealLoop v(igvn, mode); | |||
1132 | ||||
1133 | Compile* C = Compile::current(); | |||
1134 | if (!C->failing()) { | |||
1135 | // Cleanup any modified bits | |||
1136 | igvn.optimize(); | |||
1137 | ||||
1138 | v.log_loop_tree(); | |||
1139 | } | |||
1140 | } | |||
1141 | ||||
1142 | // True if the method has at least 1 irreducible loop | |||
1143 | bool _has_irreducible_loops; | |||
1144 | ||||
1145 | // Per-Node transform | |||
1146 | virtual Node* transform(Node* n) { return NULL__null; } | |||
1147 | ||||
1148 | Node* loop_exit_control(Node* x, IdealLoopTree* loop); | |||
1149 | Node* loop_exit_test(Node* back_control, IdealLoopTree* loop, Node*& incr, Node*& limit, BoolTest::mask& bt, float& cl_prob); | |||
1150 | Node* loop_iv_incr(Node* incr, Node* x, IdealLoopTree* loop, Node*& phi_incr); | |||
1151 | Node* loop_iv_stride(Node* incr, IdealLoopTree* loop, Node*& xphi); | |||
1152 | PhiNode* loop_iv_phi(Node* xphi, Node* phi_incr, Node* x, IdealLoopTree* loop); | |||
1153 | ||||
1154 | bool is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_bt); | |||
1155 | ||||
1156 | Node* loop_nest_replace_iv(Node* iv_to_replace, Node* inner_iv, Node* outer_phi, Node* inner_head, BasicType bt); | |||
1157 | bool create_loop_nest(IdealLoopTree* loop, Node_List &old_new); | |||
1158 | #ifdef ASSERT1 | |||
1159 | bool convert_to_long_loop(Node* cmp, Node* phi, IdealLoopTree* loop); | |||
1160 | #endif | |||
1161 | void add_empty_predicate(Deoptimization::DeoptReason reason, Node* inner_head, IdealLoopTree* loop, SafePointNode* sfpt); | |||
1162 | SafePointNode* find_safepoint(Node* back_control, Node* x, IdealLoopTree* loop); | |||
1163 | IdealLoopTree* insert_outer_loop(IdealLoopTree* loop, LoopNode* outer_l, Node* outer_ift); | |||
1164 | IdealLoopTree* create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, | |||
1165 | IdealLoopTree* loop, float cl_prob, float le_fcnt, | |||
1166 | Node*& entry_control, Node*& iffalse); | |||
1167 | ||||
1168 | Node* exact_limit( IdealLoopTree *loop ); | |||
1169 | ||||
1170 | // Return a post-walked LoopNode | |||
1171 | IdealLoopTree *get_loop( Node *n ) const { | |||
1172 | // Dead nodes have no loop, so return the top level loop instead | |||
1173 | if (!has_node(n)) return _ltree_root; | |||
1174 | assert(!has_ctrl(n), "")do { if (!(!has_ctrl(n))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1174, "assert(" "!has_ctrl(n)" ") failed", ""); ::breakpoint (); } } while (0); | |||
1175 | return (IdealLoopTree*)_nodes[n->_idx]; | |||
1176 | } | |||
1177 | ||||
1178 | IdealLoopTree* ltree_root() const { return _ltree_root; } | |||
1179 | ||||
1180 | // Is 'n' a (nested) member of 'loop'? | |||
1181 | int is_member( const IdealLoopTree *loop, Node *n ) const { | |||
1182 | return loop->is_member(get_loop(n)); } | |||
1183 | ||||
1184 | // This is the basic building block of the loop optimizations. It clones an | |||
1185 | // entire loop body. It makes an old_new loop body mapping; with this | |||
1186 | // mapping you can find the new-loop equivalent to an old-loop node. All | |||
1187 | // new-loop nodes are exactly equal to their old-loop counterparts, all | |||
1188 | // edges are the same. All exits from the old-loop now have a RegionNode | |||
1189 | // that merges the equivalent new-loop path. This is true even for the | |||
1190 | // normal "loop-exit" condition. All uses of loop-invariant old-loop values | |||
1191 | // now come from (one or more) Phis that merge their new-loop equivalents. | |||
1192 | // Parameter side_by_side_idom: | |||
1193 | // When side_by_size_idom is NULL, the dominator tree is constructed for | |||
1194 | // the clone loop to dominate the original. Used in construction of | |||
1195 | // pre-main-post loop sequence. | |||
1196 | // When nonnull, the clone and original are side-by-side, both are | |||
1197 | // dominated by the passed in side_by_side_idom node. Used in | |||
1198 | // construction of unswitched loops. | |||
1199 | enum CloneLoopMode { | |||
1200 | IgnoreStripMined = 0, // Only clone inner strip mined loop | |||
1201 | CloneIncludesStripMined = 1, // clone both inner and outer strip mined loops | |||
1202 | ControlAroundStripMined = 2 // Only clone inner strip mined loop, | |||
1203 | // result control flow branches | |||
1204 | // either to inner clone or outer | |||
1205 | // strip mined loop. | |||
1206 | }; | |||
1207 | void clone_loop( IdealLoopTree *loop, Node_List &old_new, int dom_depth, | |||
1208 | CloneLoopMode mode, Node* side_by_side_idom = NULL__null); | |||
1209 | void clone_loop_handle_data_uses(Node* old, Node_List &old_new, | |||
1210 | IdealLoopTree* loop, IdealLoopTree* companion_loop, | |||
1211 | Node_List*& split_if_set, Node_List*& split_bool_set, | |||
1212 | Node_List*& split_cex_set, Node_List& worklist, | |||
1213 | uint new_counter, CloneLoopMode mode); | |||
1214 | void clone_outer_loop(LoopNode* head, CloneLoopMode mode, IdealLoopTree *loop, | |||
1215 | IdealLoopTree* outer_loop, int dd, Node_List &old_new, | |||
1216 | Node_List& extra_data_nodes); | |||
1217 | ||||
1218 | // If we got the effect of peeling, either by actually peeling or by | |||
1219 | // making a pre-loop which must execute at least once, we can remove | |||
1220 | // all loop-invariant dominated tests in the main body. | |||
1221 | void peeled_dom_test_elim( IdealLoopTree *loop, Node_List &old_new ); | |||
1222 | ||||
1223 | // Generate code to do a loop peel for the given loop (and body). | |||
1224 | // old_new is a temp array. | |||
1225 | void do_peeling( IdealLoopTree *loop, Node_List &old_new ); | |||
1226 | ||||
1227 | // Add pre and post loops around the given loop. These loops are used | |||
1228 | // during RCE, unrolling and aligning loops. | |||
1229 | void insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only ); | |||
1230 | ||||
1231 | // Add post loop after the given loop. | |||
1232 | Node *insert_post_loop(IdealLoopTree* loop, Node_List& old_new, | |||
1233 | CountedLoopNode* main_head, CountedLoopEndNode* main_end, | |||
1234 | Node*& incr, Node* limit, CountedLoopNode*& post_head); | |||
1235 | ||||
1236 | // Add an RCE'd post loop which we will multi-version adapt for run time test path usage | |||
1237 | void insert_scalar_rced_post_loop( IdealLoopTree *loop, Node_List &old_new ); | |||
1238 | ||||
1239 | // Add a vector post loop between a vector main loop and the current post loop | |||
1240 | void insert_vector_post_loop(IdealLoopTree *loop, Node_List &old_new); | |||
1241 | // If Node n lives in the back_ctrl block, we clone a private version of n | |||
1242 | // in preheader_ctrl block and return that, otherwise return n. | |||
1243 | Node *clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n, VectorSet &visited, Node_Stack &clones ); | |||
1244 | ||||
1245 | // Take steps to maximally unroll the loop. Peel any odd iterations, then | |||
1246 | // unroll to do double iterations. The next round of major loop transforms | |||
1247 | // will repeat till the doubled loop body does all remaining iterations in 1 | |||
1248 | // pass. | |||
1249 | void do_maximally_unroll( IdealLoopTree *loop, Node_List &old_new ); | |||
1250 | ||||
1251 | // Unroll the loop body one step - make each trip do 2 iterations. | |||
1252 | void do_unroll( IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip ); | |||
1253 | ||||
1254 | // Mark vector reduction candidates before loop unrolling | |||
1255 | void mark_reductions( IdealLoopTree *loop ); | |||
1256 | ||||
1257 | // Return true if exp is a constant times an induction var | |||
1258 | bool is_scaled_iv(Node* exp, Node* iv, jlong* p_scale, BasicType bt, bool* converted); | |||
1259 | ||||
1260 | bool is_iv(Node* exp, Node* iv, BasicType bt); | |||
1261 | ||||
1262 | // Return true if exp is a scaled induction var plus (or minus) constant | |||
1263 | bool is_scaled_iv_plus_offset(Node* exp, Node* iv, jlong* p_scale, Node** p_offset, BasicType bt, bool* converted = NULL__null, int depth = 0); | |||
1264 | bool is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale, Node** p_offset) { | |||
1265 | jlong long_scale; | |||
1266 | if (is_scaled_iv_plus_offset(exp, iv, &long_scale, p_offset, T_INT)) { | |||
1267 | int int_scale = checked_cast<int>(long_scale); | |||
1268 | if (p_scale != NULL__null) { | |||
1269 | *p_scale = int_scale; | |||
1270 | } | |||
1271 | return true; | |||
1272 | } | |||
1273 | return false; | |||
1274 | } | |||
1275 | ||||
1276 | // Enum to determine the action to be performed in create_new_if_for_predicate() when processing phis of UCT regions. | |||
1277 | enum class UnswitchingAction { | |||
1278 | None, // No special action. | |||
1279 | FastLoopCloning, // Need to clone nodes for the fast loop. | |||
1280 | SlowLoopRewiring // Need to rewire nodes for the slow loop. | |||
1281 | }; | |||
1282 | ||||
1283 | // Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted | |||
1284 | ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry, Deoptimization::DeoptReason reason, | |||
1285 | int opcode, bool if_cont_is_true_proj = true, Node_List* old_new = NULL__null, | |||
1286 | UnswitchingAction unswitching_action = UnswitchingAction::None); | |||
1287 | ||||
1288 | // Clone data nodes for the fast loop while creating a new If with create_new_if_for_predicate. | |||
1289 | Node* clone_data_nodes_for_fast_loop(Node* phi_input, ProjNode* uncommon_proj, Node* if_uct, Node_List* old_new); | |||
1290 | ||||
1291 | void register_control(Node* n, IdealLoopTree *loop, Node* pred, bool update_body = true); | |||
1292 | ||||
1293 | static Node* skip_all_loop_predicates(Node* entry); | |||
1294 | static Node* skip_loop_predicates(Node* entry); | |||
1295 | ||||
1296 | // Find a good location to insert a predicate | |||
1297 | static ProjNode* find_predicate_insertion_point(Node* start_c, Deoptimization::DeoptReason reason); | |||
1298 | // Find a predicate | |||
1299 | static Node* find_predicate(Node* entry); | |||
1300 | // Construct a range check for a predicate if | |||
1301 | BoolNode* rc_predicate(IdealLoopTree *loop, Node* ctrl, | |||
1302 | int scale, Node* offset, | |||
1303 | Node* init, Node* limit, jint stride, | |||
1304 | Node* range, bool upper, bool &overflow, | |||
1305 | bool negate); | |||
1306 | ||||
1307 | // Implementation of the loop predication to promote checks outside the loop | |||
1308 | bool loop_predication_impl(IdealLoopTree *loop); | |||
1309 | bool loop_predication_impl_helper(IdealLoopTree *loop, ProjNode* proj, ProjNode *predicate_proj, | |||
1310 | CountedLoopNode *cl, ConNode* zero, Invariance& invar, | |||
1311 | Deoptimization::DeoptReason reason); | |||
1312 | bool loop_predication_should_follow_branches(IdealLoopTree *loop, ProjNode *predicate_proj, float& loop_trip_cnt); | |||
1313 | void loop_predication_follow_branches(Node *c, IdealLoopTree *loop, float loop_trip_cnt, | |||
1314 | PathFrequency& pf, Node_Stack& stack, VectorSet& seen, | |||
1315 | Node_List& if_proj_list); | |||
1316 | ProjNode* insert_initial_skeleton_predicate(IfNode* iff, IdealLoopTree *loop, | |||
1317 | ProjNode* proj, ProjNode *predicate_proj, | |||
1318 | ProjNode* upper_bound_proj, | |||
1319 | int scale, Node* offset, | |||
1320 | Node* init, Node* limit, jint stride, | |||
1321 | Node* rng, bool& overflow, | |||
1322 | Deoptimization::DeoptReason reason); | |||
1323 | Node* add_range_check_predicate(IdealLoopTree* loop, CountedLoopNode* cl, | |||
1324 | Node* predicate_proj, int scale_con, Node* offset, | |||
1325 | Node* limit, jint stride_con, Node* value); | |||
1326 | ||||
1327 | // Helper function to collect predicate for eliminating the useless ones | |||
1328 | void collect_potentially_useful_predicates(IdealLoopTree *loop, Unique_Node_List &predicate_opaque1); | |||
1329 | void eliminate_useless_predicates(); | |||
1330 | ||||
1331 | // Change the control input of expensive nodes to allow commoning by | |||
1332 | // IGVN when it is guaranteed to not result in a more frequent | |||
1333 | // execution of the expensive node. Return true if progress. | |||
1334 | bool process_expensive_nodes(); | |||
1335 | ||||
1336 | // Check whether node has become unreachable | |||
1337 | bool is_node_unreachable(Node *n) const { | |||
1338 | return !has_node(n) || n->is_unreachable(_igvn); | |||
1339 | } | |||
1340 | ||||
1341 | // Eliminate range-checks and other trip-counter vs loop-invariant tests. | |||
1342 | int do_range_check( IdealLoopTree *loop, Node_List &old_new ); | |||
1343 | ||||
1344 | // Check to see if do_range_check(...) cleaned the main loop of range-checks | |||
1345 | void has_range_checks(IdealLoopTree *loop); | |||
1346 | ||||
1347 | // Process post loops which have range checks and try to build a multi-version | |||
1348 | // guard to safely determine if we can execute the post loop which was RCE'd. | |||
1349 | bool multi_version_post_loops(IdealLoopTree *rce_loop, IdealLoopTree *legacy_loop); | |||
1350 | ||||
1351 | // Cause the rce'd post loop to optimized away, this happens if we cannot complete multiverioning | |||
1352 | void poison_rce_post_loop(IdealLoopTree *rce_loop); | |||
1353 | ||||
1354 | // Create a slow version of the loop by cloning the loop | |||
1355 | // and inserting an if to select fast-slow versions. | |||
1356 | // Return the inserted if. | |||
1357 | IfNode* create_slow_version_of_loop(IdealLoopTree *loop, | |||
1358 | Node_List &old_new, | |||
1359 | IfNode* unswitch_iff, | |||
1360 | CloneLoopMode mode); | |||
1361 | ||||
1362 | // Clone a loop and return the clone head (clone_loop_head). | |||
1363 | // Added nodes include int(1), int(0) - disconnected, If, IfTrue, IfFalse, | |||
1364 | // This routine was created for usage in CountedLoopReserveKit. | |||
1365 | // | |||
1366 | // int(1) -> If -> IfTrue -> original_loop_head | |||
1367 | // | | |||
1368 | // V | |||
1369 | // IfFalse -> clone_loop_head (returned by function pointer) | |||
1370 | // | |||
1371 | LoopNode* create_reserve_version_of_loop(IdealLoopTree *loop, CountedLoopReserveKit* lk); | |||
1372 | // Clone loop with an invariant test (that does not exit) and | |||
1373 | // insert a clone of the test that selects which version to | |||
1374 | // execute. | |||
1375 | void do_unswitching (IdealLoopTree *loop, Node_List &old_new); | |||
1376 | ||||
1377 | // Find candidate "if" for unswitching | |||
1378 | IfNode* find_unswitching_candidate(const IdealLoopTree *loop) const; | |||
1379 | ||||
1380 | // Range Check Elimination uses this function! | |||
1381 | // Constrain the main loop iterations so the affine function: | |||
1382 | // low_limit <= scale_con * I + offset < upper_limit | |||
1383 | // always holds true. That is, either increase the number of iterations in | |||
1384 | // the pre-loop or the post-loop until the condition holds true in the main | |||
1385 | // loop. Scale_con, offset and limit are all loop invariant. | |||
1386 | void add_constraint(jlong stride_con, jlong scale_con, Node* offset, Node* low_limit, Node* upper_limit, Node* pre_ctrl, Node** pre_limit, Node** main_limit); | |||
1387 | // Helper function for add_constraint(). | |||
1388 | Node* adjust_limit(bool reduce, Node* scale, Node* offset, Node* rc_limit, Node* old_limit, Node* pre_ctrl, bool round); | |||
1389 | ||||
1390 | // Partially peel loop up through last_peel node. | |||
1391 | bool partial_peel( IdealLoopTree *loop, Node_List &old_new ); | |||
1392 | ||||
1393 | // Create a scheduled list of nodes control dependent on ctrl set. | |||
1394 | void scheduled_nodelist( IdealLoopTree *loop, VectorSet& ctrl, Node_List &sched ); | |||
1395 | // Has a use in the vector set | |||
1396 | bool has_use_in_set( Node* n, VectorSet& vset ); | |||
1397 | // Has use internal to the vector set (ie. not in a phi at the loop head) | |||
1398 | bool has_use_internal_to_set( Node* n, VectorSet& vset, IdealLoopTree *loop ); | |||
1399 | // clone "n" for uses that are outside of loop | |||
1400 | int clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ); | |||
1401 | // clone "n" for special uses that are in the not_peeled region | |||
1402 | void clone_for_special_use_inside_loop( IdealLoopTree *loop, Node* n, | |||
1403 | VectorSet& not_peel, Node_List& sink_list, Node_List& worklist ); | |||
1404 | // Insert phi(lp_entry_val, back_edge_val) at use->in(idx) for loop lp if phi does not already exist | |||
1405 | void insert_phi_for_loop( Node* use, uint idx, Node* lp_entry_val, Node* back_edge_val, LoopNode* lp ); | |||
1406 | #ifdef ASSERT1 | |||
1407 | // Validate the loop partition sets: peel and not_peel | |||
1408 | bool is_valid_loop_partition( IdealLoopTree *loop, VectorSet& peel, Node_List& peel_list, VectorSet& not_peel ); | |||
1409 | // Ensure that uses outside of loop are of the right form | |||
1410 | bool is_valid_clone_loop_form( IdealLoopTree *loop, Node_List& peel_list, | |||
1411 | uint orig_exit_idx, uint clone_exit_idx); | |||
1412 | bool is_valid_clone_loop_exit_use( IdealLoopTree *loop, Node* use, uint exit_idx); | |||
1413 | #endif | |||
1414 | ||||
1415 | // Returns nonzero constant stride if-node is a possible iv test (otherwise returns zero.) | |||
1416 | int stride_of_possible_iv( Node* iff ); | |||
1417 | bool is_possible_iv_test( Node* iff ) { return stride_of_possible_iv(iff) != 0; } | |||
1418 | // Return the (unique) control output node that's in the loop (if it exists.) | |||
1419 | Node* stay_in_loop( Node* n, IdealLoopTree *loop); | |||
1420 | // Insert a signed compare loop exit cloned from an unsigned compare. | |||
1421 | IfNode* insert_cmpi_loop_exit(IfNode* if_cmpu, IdealLoopTree *loop); | |||
1422 | void remove_cmpi_loop_exit(IfNode* if_cmp, IdealLoopTree *loop); | |||
1423 | // Utility to register node "n" with PhaseIdealLoop | |||
1424 | void register_node(Node* n, IdealLoopTree *loop, Node* pred, int ddepth); | |||
1425 | // Utility to create an if-projection | |||
1426 | ProjNode* proj_clone(ProjNode* p, IfNode* iff); | |||
1427 | // Force the iff control output to be the live_proj | |||
1428 | Node* short_circuit_if(IfNode* iff, ProjNode* live_proj); | |||
1429 | // Insert a region before an if projection | |||
1430 | RegionNode* insert_region_before_proj(ProjNode* proj); | |||
1431 | // Insert a new if before an if projection | |||
1432 | ProjNode* insert_if_before_proj(Node* left, bool Signed, BoolTest::mask relop, Node* right, ProjNode* proj); | |||
1433 | ||||
1434 | // Passed in a Phi merging (recursively) some nearly equivalent Bool/Cmps. | |||
1435 | // "Nearly" because all Nodes have been cloned from the original in the loop, | |||
1436 | // but the fall-in edges to the Cmp are different. Clone bool/Cmp pairs | |||
1437 | // through the Phi recursively, and return a Bool. | |||
1438 | Node *clone_iff( PhiNode *phi, IdealLoopTree *loop ); | |||
1439 | CmpNode *clone_bool( PhiNode *phi, IdealLoopTree *loop ); | |||
1440 | ||||
1441 | ||||
1442 | // Rework addressing expressions to get the most loop-invariant stuff | |||
1443 | // moved out. We'd like to do all associative operators, but it's especially | |||
1444 | // important (common) to do address expressions. | |||
1445 | Node *remix_address_expressions( Node *n ); | |||
1446 | ||||
1447 | // Convert add to muladd to generate MuladdS2I under certain criteria | |||
1448 | Node * convert_add_to_muladd(Node * n); | |||
1449 | ||||
1450 | // Attempt to use a conditional move instead of a phi/branch | |||
1451 | Node *conditional_move( Node *n ); | |||
1452 | ||||
1453 | // Reorganize offset computations to lower register pressure. | |||
1454 | // Mostly prevent loop-fallout uses of the pre-incremented trip counter | |||
1455 | // (which are then alive with the post-incremented trip counter | |||
1456 | // forcing an extra register move) | |||
1457 | void reorg_offsets( IdealLoopTree *loop ); | |||
1458 | ||||
1459 | // Check for aggressive application of 'split-if' optimization, | |||
1460 | // using basic block level info. | |||
1461 | void split_if_with_blocks ( VectorSet &visited, Node_Stack &nstack); | |||
1462 | Node *split_if_with_blocks_pre ( Node *n ); | |||
1463 | void split_if_with_blocks_post( Node *n ); | |||
1464 | Node *has_local_phi_input( Node *n ); | |||
1465 | // Mark an IfNode as being dominated by a prior test, | |||
1466 | // without actually altering the CFG (and hence IDOM info). | |||
1467 | void dominated_by( Node *prevdom, Node *iff, bool flip = false, bool exclude_loop_predicate = false ); | |||
1468 | ||||
1469 | // Split Node 'n' through merge point | |||
1470 | Node *split_thru_region( Node *n, Node *region ); | |||
1471 | // Split Node 'n' through merge point if there is enough win. | |||
1472 | Node *split_thru_phi( Node *n, Node *region, int policy ); | |||
1473 | // Found an If getting its condition-code input from a Phi in the | |||
1474 | // same block. Split thru the Region. | |||
1475 | void do_split_if( Node *iff ); | |||
1476 | ||||
1477 | // Conversion of fill/copy patterns into intrinsic versions | |||
1478 | bool do_intrinsify_fill(); | |||
1479 | bool intrinsify_fill(IdealLoopTree* lpt); | |||
1480 | bool match_fill_loop(IdealLoopTree* lpt, Node*& store, Node*& store_value, | |||
1481 | Node*& shift, Node*& offset); | |||
1482 | ||||
1483 | private: | |||
1484 | // Return a type based on condition control flow | |||
1485 | const TypeInt* filtered_type( Node *n, Node* n_ctrl); | |||
1486 | const TypeInt* filtered_type( Node *n ) { return filtered_type(n, NULL__null); } | |||
1487 | // Helpers for filtered type | |||
1488 | const TypeInt* filtered_type_from_dominators( Node* val, Node *val_ctrl); | |||
1489 | ||||
1490 | // Helper functions | |||
1491 | Node *spinup( Node *iff, Node *new_false, Node *new_true, Node *region, Node *phi, small_cache *cache ); | |||
1492 | Node *find_use_block( Node *use, Node *def, Node *old_false, Node *new_false, Node *old_true, Node *new_true ); | |||
1493 | void handle_use( Node *use, Node *def, small_cache *cache, Node *region_dom, Node *new_false, Node *new_true, Node *old_false, Node *old_true ); | |||
1494 | bool split_up( Node *n, Node *blk1, Node *blk2 ); | |||
1495 | void sink_use( Node *use, Node *post_loop ); | |||
1496 | Node* place_outside_loop(Node* useblock, IdealLoopTree* loop) const; | |||
1497 | Node* try_move_store_before_loop(Node* n, Node *n_ctrl); | |||
1498 | void try_move_store_after_loop(Node* n); | |||
1499 | bool identical_backtoback_ifs(Node *n); | |||
1500 | bool can_split_if(Node *n_ctrl); | |||
1501 | ||||
1502 | // Determine if a method is too big for a/another round of split-if, based on | |||
1503 | // a magic (approximate) ratio derived from the equally magic constant 35000, | |||
1504 | // previously used for this purpose (but without relating to the node limit). | |||
1505 | bool must_throttle_split_if() { | |||
1506 | uint threshold = C->max_node_limit() * 2 / 5; | |||
1507 | return C->live_nodes() > threshold; | |||
1508 | } | |||
1509 | ||||
1510 | // A simplistic node request tracking mechanism, where | |||
1511 | // = UINT_MAX Request not valid or made final. | |||
1512 | // < UINT_MAX Nodes currently requested (estimate). | |||
1513 | uint _nodes_required; | |||
1514 | ||||
1515 | enum { REQUIRE_MIN = 70 }; | |||
1516 | ||||
1517 | uint nodes_required() const { return _nodes_required; } | |||
1518 | ||||
1519 | // Given the _currently_ available number of nodes, check whether there is | |||
1520 | // "room" for an additional request or not, considering the already required | |||
1521 | // number of nodes. Return TRUE if the new request is exceeding the node | |||
1522 | // budget limit, otherwise return FALSE. Note that this interpretation will | |||
1523 | // act pessimistic on additional requests when new nodes have already been | |||
1524 | // generated since the 'begin'. This behaviour fits with the intention that | |||
1525 | // node estimates/requests should be made upfront. | |||
1526 | bool exceeding_node_budget(uint required = 0) { | |||
1527 | assert(C->live_nodes() < C->max_node_limit(), "sanity")do { if (!(C->live_nodes() < C->max_node_limit())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1527, "assert(" "C->live_nodes() < C->max_node_limit()" ") failed", "sanity"); ::breakpoint(); } } while (0); | |||
1528 | uint available = C->max_node_limit() - C->live_nodes(); | |||
1529 | return available < required + _nodes_required + REQUIRE_MIN; | |||
1530 | } | |||
1531 | ||||
1532 | uint require_nodes(uint require, uint minreq = REQUIRE_MIN) { | |||
1533 | precond(require > 0)do { if (!(require > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1533, "assert(" "require > 0" ") failed", "precond"); :: breakpoint(); } } while (0); | |||
1534 | _nodes_required += MAX2(require, minreq); | |||
1535 | return _nodes_required; | |||
1536 | } | |||
1537 | ||||
1538 | bool may_require_nodes(uint require, uint minreq = REQUIRE_MIN) { | |||
1539 | return !exceeding_node_budget(require) && require_nodes(require, minreq) > 0; | |||
1540 | } | |||
1541 | ||||
1542 | uint require_nodes_begin() { | |||
1543 | assert(_nodes_required == UINT_MAX, "Bad state (begin).")do { if (!(_nodes_required == (2147483647 *2U +1U))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1543, "assert(" "_nodes_required == (2147483647 *2U +1U)" ") failed" , "Bad state (begin)."); ::breakpoint(); } } while (0); | |||
1544 | _nodes_required = 0; | |||
1545 | return C->live_nodes(); | |||
1546 | } | |||
1547 | ||||
1548 | // When a node request is final, optionally check that the requested number | |||
1549 | // of nodes was reasonably correct with respect to the number of new nodes | |||
1550 | // introduced since the last 'begin'. Always check that we have not exceeded | |||
1551 | // the maximum node limit. | |||
1552 | void require_nodes_final(uint live_at_begin, bool check_estimate) { | |||
1553 | assert(_nodes_required < UINT_MAX, "Bad state (final).")do { if (!(_nodes_required < (2147483647 *2U +1U))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1553, "assert(" "_nodes_required < (2147483647 *2U +1U)" ") failed", "Bad state (final)."); ::breakpoint(); } } while (0); | |||
1554 | ||||
1555 | #ifdef ASSERT1 | |||
1556 | if (check_estimate) { | |||
1557 | // Check that the node budget request was not off by too much (x2). | |||
1558 | // Should this be the case we _surely_ need to improve the estimates | |||
1559 | // used in our budget calculations. | |||
1560 | if (C->live_nodes() - live_at_begin > 2 * _nodes_required) { | |||
1561 | log_info(compilation)(!(LogImpl<(LogTag::_compilation), (LogTag::__NO_TAG), (LogTag ::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag:: __NO_TAG)>::is_level(LogLevel::Info))) ? (void)0 : LogImpl <(LogTag::_compilation), (LogTag::__NO_TAG), (LogTag::__NO_TAG ), (LogTag::__NO_TAG), (LogTag::__NO_TAG), (LogTag::__NO_TAG) >::write<LogLevel::Info>("Bad node estimate: actual = %d >> request = %d", | |||
1562 | C->live_nodes() - live_at_begin, _nodes_required); | |||
1563 | } | |||
1564 | } | |||
1565 | #endif | |||
1566 | // Assert that we have stayed within the node budget limit. | |||
1567 | assert(C->live_nodes() < C->max_node_limit(),do { if (!(C->live_nodes() < C->max_node_limit())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1570, "assert(" "C->live_nodes() < C->max_node_limit()" ") failed", "Exceeding node budget limit: %d + %d > %d (request = %d)" , C->live_nodes() - live_at_begin, live_at_begin, C->max_node_limit (), _nodes_required); ::breakpoint(); } } while (0) | |||
1568 | "Exceeding node budget limit: %d + %d > %d (request = %d)",do { if (!(C->live_nodes() < C->max_node_limit())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1570, "assert(" "C->live_nodes() < C->max_node_limit()" ") failed", "Exceeding node budget limit: %d + %d > %d (request = %d)" , C->live_nodes() - live_at_begin, live_at_begin, C->max_node_limit (), _nodes_required); ::breakpoint(); } } while (0) | |||
1569 | C->live_nodes() - live_at_begin, live_at_begin,do { if (!(C->live_nodes() < C->max_node_limit())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1570, "assert(" "C->live_nodes() < C->max_node_limit()" ") failed", "Exceeding node budget limit: %d + %d > %d (request = %d)" , C->live_nodes() - live_at_begin, live_at_begin, C->max_node_limit (), _nodes_required); ::breakpoint(); } } while (0) | |||
1570 | C->max_node_limit(), _nodes_required)do { if (!(C->live_nodes() < C->max_node_limit())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1570, "assert(" "C->live_nodes() < C->max_node_limit()" ") failed", "Exceeding node budget limit: %d + %d > %d (request = %d)" , C->live_nodes() - live_at_begin, live_at_begin, C->max_node_limit (), _nodes_required); ::breakpoint(); } } while (0); | |||
1571 | ||||
1572 | _nodes_required = UINT_MAX(2147483647 *2U +1U); | |||
1573 | } | |||
1574 | ||||
1575 | // Clone loop predicates to slow and fast loop when unswitching a loop | |||
1576 | void clone_predicates_to_unswitched_loop(IdealLoopTree* loop, Node_List& old_new, ProjNode*& iffast_pred, ProjNode*& ifslow_pred); | |||
1577 | ProjNode* clone_predicate_to_unswitched_loop(ProjNode* predicate_proj, Node* new_entry, Deoptimization::DeoptReason reason, | |||
1578 | Node_List* old_new = NULL__null); | |||
1579 | void clone_skeleton_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, Deoptimization::DeoptReason reason, | |||
1580 | ProjNode* old_predicate_proj, ProjNode* iffast_pred, ProjNode* ifslow_pred); | |||
1581 | ProjNode* clone_skeleton_predicate_for_unswitched_loops(Node* iff, ProjNode* predicate, | |||
1582 | Deoptimization::DeoptReason reason, | |||
1583 | ProjNode* output_proj); | |||
1584 | static void check_created_predicate_for_unswitching(const Node* new_entry) PRODUCT_RETURN; | |||
1585 | ||||
1586 | bool _created_loop_node; | |||
1587 | #ifdef ASSERT1 | |||
1588 | void dump_real_LCA(Node* early, Node* wrong_lca); | |||
1589 | bool check_idom_chains_intersection(const Node* n, uint& idom_idx_new, uint& idom_idx_other, const Node_List* nodes_seen) const; | |||
1590 | #endif | |||
1591 | ||||
1592 | public: | |||
1593 | void set_created_loop_node() { _created_loop_node = true; } | |||
1594 | bool created_loop_node() { return _created_loop_node; } | |||
1595 | void register_new_node(Node* n, Node* blk); | |||
1596 | ||||
1597 | #ifdef ASSERT1 | |||
1598 | void dump_bad_graph(const char* msg, Node* n, Node* early, Node* LCA); | |||
1599 | #endif | |||
1600 | ||||
1601 | #ifndef PRODUCT | |||
1602 | void dump() const; | |||
1603 | void dump_idom(Node* n) const; | |||
1604 | void dump(IdealLoopTree* loop, uint rpo_idx, Node_List &rpo_list) const; | |||
1605 | void verify() const; // Major slow :-) | |||
1606 | void verify_compare(Node* n, const PhaseIdealLoop* loop_verify, VectorSet &visited) const; | |||
1607 | IdealLoopTree* get_loop_idx(Node* n) const { | |||
1608 | // Dead nodes have no loop, so return the top level loop instead | |||
1609 | return _nodes[n->_idx] ? (IdealLoopTree*)_nodes[n->_idx] : _ltree_root; | |||
1610 | } | |||
1611 | // Print some stats | |||
1612 | static void print_statistics(); | |||
1613 | static int _loop_invokes; // Count of PhaseIdealLoop invokes | |||
1614 | static int _loop_work; // Sum of PhaseIdealLoop x _unique | |||
1615 | static volatile int _long_loop_candidates; | |||
1616 | static volatile int _long_loop_nests; | |||
1617 | static volatile int _long_loop_counted_loops; | |||
1618 | #endif | |||
1619 | ||||
1620 | void rpo(Node* start, Node_Stack &stk, VectorSet &visited, Node_List &rpo_list) const; | |||
1621 | ||||
1622 | void check_counted_loop_shape(IdealLoopTree* loop, Node* x, BasicType bt) NOT_DEBUG_RETURN; | |||
1623 | ||||
1624 | LoopNode* create_inner_head(IdealLoopTree* loop, BaseCountedLoopNode* head, IfNode* exit_test); | |||
1625 | ||||
1626 | ||||
1627 | int extract_long_range_checks(const IdealLoopTree* loop, jlong stride_con, int iters_limit, PhiNode* phi, | |||
1628 | Node_List &range_checks); | |||
1629 | ||||
1630 | void transform_long_range_checks(int stride_con, const Node_List &range_checks, Node* outer_phi, | |||
1631 | Node* inner_iters_actual_int, Node* inner_phi, | |||
1632 | Node* iv_add, LoopNode* inner_head); | |||
1633 | ||||
1634 | Node* get_late_ctrl_with_anti_dep(LoadNode* n, Node* early, Node* LCA); | |||
1635 | ||||
1636 | bool ctrl_of_use_out_of_loop(const Node* n, Node* n_ctrl, IdealLoopTree* n_loop, Node* ctrl); | |||
1637 | ||||
1638 | bool ctrl_of_all_uses_out_of_loop(const Node* n, Node* n_ctrl, IdealLoopTree* n_loop); | |||
1639 | ||||
1640 | Node* compute_early_ctrl(Node* n, Node* n_ctrl); | |||
1641 | ||||
1642 | void try_sink_out_of_loop(Node* n); | |||
1643 | ||||
1644 | Node* clamp(Node* R, Node* L, Node* H); | |||
1645 | ||||
1646 | bool safe_for_if_replacement(const Node* dom) const; | |||
1647 | ||||
1648 | void strip_mined_nest_back_to_counted_loop(IdealLoopTree* loop, const BaseCountedLoopNode* head, Node* back_control, | |||
1649 | IfNode*&exit_test, SafePointNode*&safepoint); | |||
1650 | }; | |||
1651 | ||||
1652 | ||||
1653 | class AutoNodeBudget : public StackObj | |||
1654 | { | |||
1655 | public: | |||
1656 | enum budget_check_t { BUDGET_CHECK, NO_BUDGET_CHECK }; | |||
1657 | ||||
1658 | AutoNodeBudget(PhaseIdealLoop* phase, budget_check_t chk = BUDGET_CHECK) | |||
1659 | : _phase(phase), | |||
1660 | _check_at_final(chk == BUDGET_CHECK), | |||
1661 | _nodes_at_begin(0) | |||
1662 | { | |||
1663 | precond(_phase != NULL)do { if (!(_phase != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopnode.hpp" , 1663, "assert(" "_phase != __null" ") failed", "precond"); :: breakpoint(); } } while (0); | |||
1664 | ||||
1665 | _nodes_at_begin = _phase->require_nodes_begin(); | |||
1666 | } | |||
1667 | ||||
1668 | ~AutoNodeBudget() { | |||
1669 | #ifndef PRODUCT | |||
1670 | if (TraceLoopOpts) { | |||
1671 | uint request = _phase->nodes_required(); | |||
1672 | uint delta = _phase->C->live_nodes() - _nodes_at_begin; | |||
1673 | ||||
1674 | if (request < delta) { | |||
1675 | tty->print_cr("Exceeding node budget: %d < %d", request, delta); | |||
1676 | } else { | |||
1677 | uint const REQUIRE_MIN = PhaseIdealLoop::REQUIRE_MIN; | |||
1678 | // Identify the worst estimates as "poor" ones. | |||
1679 | if (request > REQUIRE_MIN && delta > 0) { | |||
1680 | if ((delta > REQUIRE_MIN && request > 3 * delta) || | |||
1681 | (delta <= REQUIRE_MIN && request > 10 * delta)) { | |||
1682 | tty->print_cr("Poor node estimate: %d >> %d", request, delta); | |||
1683 | } | |||
1684 | } | |||
1685 | } | |||
1686 | } | |||
1687 | #endif // PRODUCT | |||
1688 | _phase->require_nodes_final(_nodes_at_begin, _check_at_final); | |||
1689 | } | |||
1690 | ||||
1691 | private: | |||
1692 | PhaseIdealLoop* _phase; | |||
1693 | bool _check_at_final; | |||
1694 | uint _nodes_at_begin; | |||
1695 | }; | |||
1696 | ||||
1697 | ||||
1698 | // This kit may be used for making of a reserved copy of a loop before this loop | |||
1699 | // goes under non-reversible changes. | |||
1700 | // | |||
1701 | // Function create_reserve() creates a reserved copy (clone) of the loop. | |||
1702 | // The reserved copy is created by calling | |||
1703 | // PhaseIdealLoop::create_reserve_version_of_loop - see there how | |||
1704 | // the original and reserved loops are connected in the outer graph. | |||
1705 | // If create_reserve succeeded, it returns 'true' and _has_reserved is set to 'true'. | |||
1706 | // | |||
1707 | // By default the reserved copy (clone) of the loop is created as dead code - it is | |||
1708 | // dominated in the outer loop by this node chain: | |||
1709 | // intcon(1)->If->IfFalse->reserved_copy. | |||
1710 | // The original loop is dominated by the the same node chain but IfTrue projection: | |||
1711 | // intcon(0)->If->IfTrue->original_loop. | |||
1712 | // | |||
1713 | // In this implementation of CountedLoopReserveKit the ctor includes create_reserve() | |||
1714 | // and the dtor, checks _use_new value. | |||
1715 | // If _use_new == false, it "switches" control to reserved copy of the loop | |||
1716 | // by simple replacing of node intcon(1) with node intcon(0). | |||
1717 | // | |||
1718 | // Here is a proposed example of usage (see also SuperWord::output in superword.cpp). | |||
1719 | // | |||
1720 | // void CountedLoopReserveKit_example() | |||
1721 | // { | |||
1722 | // CountedLoopReserveKit lrk((phase, lpt, DoReserveCopy = true); // create local object | |||
1723 | // if (DoReserveCopy && !lrk.has_reserved()) { | |||
1724 | // return; //failed to create reserved loop copy | |||
1725 | // } | |||
1726 | // ... | |||
1727 | // //something is wrong, switch to original loop | |||
1728 | /// if(something_is_wrong) return; // ~CountedLoopReserveKit makes the switch | |||
1729 | // ... | |||
1730 | // //everything worked ok, return with the newly modified loop | |||
1731 | // lrk.use_new(); | |||
1732 | // return; // ~CountedLoopReserveKit does nothing once use_new() was called | |||
1733 | // } | |||
1734 | // | |||
1735 | // Keep in mind, that by default if create_reserve() is not followed by use_new() | |||
1736 | // the dtor will "switch to the original" loop. | |||
1737 | // NOTE. You you modify outside of the original loop this class is no help. | |||
1738 | // | |||
1739 | class CountedLoopReserveKit { | |||
1740 | private: | |||
1741 | PhaseIdealLoop* _phase; | |||
1742 | IdealLoopTree* _lpt; | |||
1743 | LoopNode* _lp; | |||
1744 | IfNode* _iff; | |||
1745 | LoopNode* _lp_reserved; | |||
1746 | bool _has_reserved; | |||
1747 | bool _use_new; | |||
1748 | const bool _active; //may be set to false in ctor, then the object is dummy | |||
1749 | ||||
1750 | public: | |||
1751 | CountedLoopReserveKit(PhaseIdealLoop* phase, IdealLoopTree *loop, bool active); | |||
1752 | ~CountedLoopReserveKit(); | |||
1753 | void use_new() {_use_new = true;} | |||
1754 | void set_iff(IfNode* x) {_iff = x;} | |||
1755 | bool has_reserved() const { return _active && _has_reserved;} | |||
1756 | private: | |||
1757 | bool create_reserve(); | |||
1758 | };// class CountedLoopReserveKit | |||
1759 | ||||
1760 | inline Node* IdealLoopTree::tail() { | |||
1761 | // Handle lazy update of _tail field. | |||
1762 | if (_tail->in(0) == NULL__null) { | |||
1763 | _tail = _phase->get_ctrl(_tail); | |||
1764 | } | |||
1765 | return _tail; | |||
1766 | } | |||
1767 | ||||
1768 | inline Node* IdealLoopTree::head() { | |||
1769 | // Handle lazy update of _head field. | |||
1770 | if (_head->in(0) == NULL__null) { | |||
1771 | _head = _phase->get_ctrl(_head); | |||
1772 | } | |||
1773 | return _head; | |||
1774 | } | |||
1775 | ||||
1776 | // Iterate over the loop tree using a preorder, left-to-right traversal. | |||
1777 | // | |||
1778 | // Example that visits all counted loops from within PhaseIdealLoop | |||
1779 | // | |||
1780 | // for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) { | |||
1781 | // IdealLoopTree* lpt = iter.current(); | |||
1782 | // if (!lpt->is_counted()) continue; | |||
1783 | // ... | |||
1784 | class LoopTreeIterator : public StackObj { | |||
1785 | private: | |||
1786 | IdealLoopTree* _root; | |||
1787 | IdealLoopTree* _curnt; | |||
1788 | ||||
1789 | public: | |||
1790 | LoopTreeIterator(IdealLoopTree* root) : _root(root), _curnt(root) {} | |||
1791 | ||||
1792 | bool done() { return _curnt == NULL__null; } // Finished iterating? | |||
1793 | ||||
1794 | void next(); // Advance to next loop tree | |||
1795 | ||||
1796 | IdealLoopTree* current() { return _curnt; } // Return current value of iterator. | |||
1797 | }; | |||
1798 | ||||
1799 | #endif // SHARE_OPTO_LOOPNODE_HPP |