File: | jdk/src/hotspot/share/opto/loopopts.cpp |
Warning: | line 1104, column 34 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | ||||||
2 | * Copyright (c) 1999, 2019, 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 "gc/shared/barrierSet.hpp" | ||||||
27 | #include "gc/shared/c2/barrierSetC2.hpp" | ||||||
28 | #include "memory/allocation.inline.hpp" | ||||||
29 | #include "memory/resourceArea.hpp" | ||||||
30 | #include "opto/addnode.hpp" | ||||||
31 | #include "opto/callnode.hpp" | ||||||
32 | #include "opto/castnode.hpp" | ||||||
33 | #include "opto/connode.hpp" | ||||||
34 | #include "opto/castnode.hpp" | ||||||
35 | #include "opto/divnode.hpp" | ||||||
36 | #include "opto/loopnode.hpp" | ||||||
37 | #include "opto/matcher.hpp" | ||||||
38 | #include "opto/mulnode.hpp" | ||||||
39 | #include "opto/movenode.hpp" | ||||||
40 | #include "opto/opaquenode.hpp" | ||||||
41 | #include "opto/rootnode.hpp" | ||||||
42 | #include "opto/subnode.hpp" | ||||||
43 | #include "opto/subtypenode.hpp" | ||||||
44 | #include "utilities/macros.hpp" | ||||||
45 | |||||||
46 | //============================================================================= | ||||||
47 | //------------------------------split_thru_phi--------------------------------- | ||||||
48 | // Split Node 'n' through merge point if there is enough win. | ||||||
49 | Node* PhaseIdealLoop::split_thru_phi(Node* n, Node* region, int policy) { | ||||||
50 | if (n->Opcode() == Op_ConvI2L && n->bottom_type() != TypeLong::LONG) { | ||||||
51 | // ConvI2L may have type information on it which is unsafe to push up | ||||||
52 | // so disable this for now | ||||||
53 | return NULL__null; | ||||||
54 | } | ||||||
55 | |||||||
56 | // Splitting range check CastIIs through a loop induction Phi can | ||||||
57 | // cause new Phis to be created that are left unrelated to the loop | ||||||
58 | // induction Phi and prevent optimizations (vectorization) | ||||||
59 | if (n->Opcode() == Op_CastII && region->is_CountedLoop() && | ||||||
60 | n->in(1) == region->as_CountedLoop()->phi()) { | ||||||
61 | return NULL__null; | ||||||
62 | } | ||||||
63 | |||||||
64 | // Bail out if 'n' is a Div or Mod node whose zero check was removed earlier (i.e. control is NULL) and its divisor is an induction variable | ||||||
65 | // phi p of a trip-counted (integer) loop whose inputs could be zero (include zero in their type range). p could have a more precise type | ||||||
66 | // range that does not necessarily include all values of its inputs. Since each of these inputs will be a divisor of the newly cloned nodes | ||||||
67 | // of 'n', we need to bail out of one of these divisors could be zero (zero in its type range). | ||||||
68 | if ((n->Opcode() == Op_DivI || n->Opcode() == Op_ModI) && n->in(0) == NULL__null | ||||||
69 | && region->is_CountedLoop() && n->in(2) == region->as_CountedLoop()->phi()) { | ||||||
70 | Node* phi = region->as_CountedLoop()->phi(); | ||||||
71 | for (uint i = 1; i < phi->req(); i++) { | ||||||
72 | if (_igvn.type(phi->in(i))->filter_speculative(TypeInt::ZERO) != Type::TOP) { | ||||||
73 | // Zero could be a possible value but we already removed the zero check. Bail out to avoid a possible division by zero at a later point. | ||||||
74 | return NULL__null; | ||||||
75 | } | ||||||
76 | } | ||||||
77 | } | ||||||
78 | |||||||
79 | int wins = 0; | ||||||
80 | 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/loopopts.cpp" , 80, "assert(" "!n->is_CFG()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
81 | 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/loopopts.cpp" , 81, "assert(" "region->is_Region()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
82 | |||||||
83 | const Type* type = n->bottom_type(); | ||||||
84 | const TypeOopPtr* t_oop = _igvn.type(n)->isa_oopptr(); | ||||||
85 | Node* phi; | ||||||
86 | if (t_oop != NULL__null && t_oop->is_known_instance_field()) { | ||||||
87 | int iid = t_oop->instance_id(); | ||||||
88 | int index = C->get_alias_index(t_oop); | ||||||
89 | int offset = t_oop->offset(); | ||||||
90 | phi = new PhiNode(region, type, NULL__null, iid, index, offset); | ||||||
91 | } else { | ||||||
92 | phi = PhiNode::make_blank(region, n); | ||||||
93 | } | ||||||
94 | uint old_unique = C->unique(); | ||||||
95 | for (uint i = 1; i < region->req(); i++) { | ||||||
96 | Node* x; | ||||||
97 | Node* the_clone = NULL__null; | ||||||
98 | if (region->in(i) == C->top()) { | ||||||
99 | x = C->top(); // Dead path? Use a dead data op | ||||||
100 | } else { | ||||||
101 | x = n->clone(); // Else clone up the data op | ||||||
102 | the_clone = x; // Remember for possible deletion. | ||||||
103 | // Alter data node to use pre-phi inputs | ||||||
104 | if (n->in(0) == region) | ||||||
105 | x->set_req( 0, region->in(i) ); | ||||||
106 | for (uint j = 1; j < n->req(); j++) { | ||||||
107 | Node* in = n->in(j); | ||||||
108 | if (in->is_Phi() && in->in(0) == region) | ||||||
109 | x->set_req(j, in->in(i)); // Use pre-Phi input for the clone | ||||||
110 | } | ||||||
111 | } | ||||||
112 | // Check for a 'win' on some paths | ||||||
113 | const Type* t = x->Value(&_igvn); | ||||||
114 | |||||||
115 | bool singleton = t->singleton(); | ||||||
116 | |||||||
117 | // A TOP singleton indicates that there are no possible values incoming | ||||||
118 | // along a particular edge. In most cases, this is OK, and the Phi will | ||||||
119 | // be eliminated later in an Ideal call. However, we can't allow this to | ||||||
120 | // happen if the singleton occurs on loop entry, as the elimination of | ||||||
121 | // the PhiNode may cause the resulting node to migrate back to a previous | ||||||
122 | // loop iteration. | ||||||
123 | if (singleton && t == Type::TOP) { | ||||||
124 | // Is_Loop() == false does not confirm the absence of a loop (e.g., an | ||||||
125 | // irreducible loop may not be indicated by an affirmative is_Loop()); | ||||||
126 | // therefore, the only top we can split thru a phi is on a backedge of | ||||||
127 | // a loop. | ||||||
128 | singleton &= region->is_Loop() && (i != LoopNode::EntryControl); | ||||||
129 | } | ||||||
130 | |||||||
131 | if (singleton) { | ||||||
132 | wins++; | ||||||
133 | x = ((PhaseGVN&)_igvn).makecon(t); | ||||||
134 | } else { | ||||||
135 | // We now call Identity to try to simplify the cloned node. | ||||||
136 | // Note that some Identity methods call phase->type(this). | ||||||
137 | // Make sure that the type array is big enough for | ||||||
138 | // our new node, even though we may throw the node away. | ||||||
139 | // (Note: This tweaking with igvn only works because x is a new node.) | ||||||
140 | _igvn.set_type(x, t); | ||||||
141 | // If x is a TypeNode, capture any more-precise type permanently into Node | ||||||
142 | // otherwise it will be not updated during igvn->transform since | ||||||
143 | // igvn->type(x) is set to x->Value() already. | ||||||
144 | x->raise_bottom_type(t); | ||||||
145 | Node* y = x->Identity(&_igvn); | ||||||
146 | if (y != x) { | ||||||
147 | wins++; | ||||||
148 | x = y; | ||||||
149 | } else { | ||||||
150 | y = _igvn.hash_find(x); | ||||||
151 | if (y) { | ||||||
152 | wins++; | ||||||
153 | x = y; | ||||||
154 | } else { | ||||||
155 | // Else x is a new node we are keeping | ||||||
156 | // We do not need register_new_node_with_optimizer | ||||||
157 | // because set_type has already been called. | ||||||
158 | _igvn._worklist.push(x); | ||||||
159 | } | ||||||
160 | } | ||||||
161 | } | ||||||
162 | if (x != the_clone && the_clone != NULL__null) | ||||||
163 | _igvn.remove_dead_node(the_clone); | ||||||
164 | phi->set_req( i, x ); | ||||||
165 | } | ||||||
166 | // Too few wins? | ||||||
167 | if (wins <= policy) { | ||||||
168 | _igvn.remove_dead_node(phi); | ||||||
169 | return NULL__null; | ||||||
170 | } | ||||||
171 | |||||||
172 | // Record Phi | ||||||
173 | register_new_node( phi, region ); | ||||||
174 | |||||||
175 | for (uint i2 = 1; i2 < phi->req(); i2++) { | ||||||
176 | Node *x = phi->in(i2); | ||||||
177 | // If we commoned up the cloned 'x' with another existing Node, | ||||||
178 | // the existing Node picks up a new use. We need to make the | ||||||
179 | // existing Node occur higher up so it dominates its uses. | ||||||
180 | Node *old_ctrl; | ||||||
181 | IdealLoopTree *old_loop; | ||||||
182 | |||||||
183 | if (x->is_Con()) { | ||||||
184 | // Constant's control is always root. | ||||||
185 | set_ctrl(x, C->root()); | ||||||
186 | continue; | ||||||
187 | } | ||||||
188 | // The occasional new node | ||||||
189 | if (x->_idx >= old_unique) { // Found a new, unplaced node? | ||||||
190 | old_ctrl = NULL__null; | ||||||
191 | old_loop = NULL__null; // Not in any prior loop | ||||||
192 | } else { | ||||||
193 | old_ctrl = get_ctrl(x); | ||||||
194 | old_loop = get_loop(old_ctrl); // Get prior loop | ||||||
195 | } | ||||||
196 | // New late point must dominate new use | ||||||
197 | Node *new_ctrl = dom_lca(old_ctrl, region->in(i2)); | ||||||
198 | if (new_ctrl == old_ctrl) // Nothing is changed | ||||||
199 | continue; | ||||||
200 | |||||||
201 | IdealLoopTree *new_loop = get_loop(new_ctrl); | ||||||
202 | |||||||
203 | // Don't move x into a loop if its uses are | ||||||
204 | // outside of loop. Otherwise x will be cloned | ||||||
205 | // for each use outside of this loop. | ||||||
206 | IdealLoopTree *use_loop = get_loop(region); | ||||||
207 | if (!new_loop->is_member(use_loop) && | ||||||
208 | (old_loop == NULL__null || !new_loop->is_member(old_loop))) { | ||||||
209 | // Take early control, later control will be recalculated | ||||||
210 | // during next iteration of loop optimizations. | ||||||
211 | new_ctrl = get_early_ctrl(x); | ||||||
212 | new_loop = get_loop(new_ctrl); | ||||||
213 | } | ||||||
214 | // Set new location | ||||||
215 | set_ctrl(x, new_ctrl); | ||||||
216 | // If changing loop bodies, see if we need to collect into new body | ||||||
217 | if (old_loop != new_loop) { | ||||||
218 | if (old_loop && !old_loop->_child) | ||||||
219 | old_loop->_body.yank(x); | ||||||
220 | if (!new_loop->_child) | ||||||
221 | new_loop->_body.push(x); // Collect body info | ||||||
222 | } | ||||||
223 | } | ||||||
224 | |||||||
225 | return phi; | ||||||
226 | } | ||||||
227 | |||||||
228 | //------------------------------dominated_by------------------------------------ | ||||||
229 | // Replace the dominated test with an obvious true or false. Place it on the | ||||||
230 | // IGVN worklist for later cleanup. Move control-dependent data Nodes on the | ||||||
231 | // live path up to the dominating control. | ||||||
232 | void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff, bool flip, bool exclude_loop_predicate ) { | ||||||
233 | if (VerifyLoopOptimizations && PrintOpto) { tty->print_cr("dominating test"); } | ||||||
234 | |||||||
235 | // prevdom is the dominating projection of the dominating test. | ||||||
236 | assert(iff->is_If(), "must be")do { if (!(iff->is_If())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 236, "assert(" "iff->is_If()" ") failed", "must be"); :: breakpoint(); } } while (0); | ||||||
237 | assert(iff->Opcode() == Op_If ||do { if (!(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode () == Op_RangeCheck)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 241, "assert(" "iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode() == Op_RangeCheck" ") failed", "Check this code when new subtype is added"); :: breakpoint(); } } while (0) | ||||||
238 | iff->Opcode() == Op_CountedLoopEnd ||do { if (!(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode () == Op_RangeCheck)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 241, "assert(" "iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode() == Op_RangeCheck" ") failed", "Check this code when new subtype is added"); :: breakpoint(); } } while (0) | ||||||
239 | iff->Opcode() == Op_LongCountedLoopEnd ||do { if (!(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode () == Op_RangeCheck)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 241, "assert(" "iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode() == Op_RangeCheck" ") failed", "Check this code when new subtype is added"); :: breakpoint(); } } while (0) | ||||||
240 | iff->Opcode() == Op_RangeCheck,do { if (!(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode () == Op_RangeCheck)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 241, "assert(" "iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode() == Op_RangeCheck" ") failed", "Check this code when new subtype is added"); :: breakpoint(); } } while (0) | ||||||
241 | "Check this code when new subtype is added")do { if (!(iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode () == Op_RangeCheck)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 241, "assert(" "iff->Opcode() == Op_If || iff->Opcode() == Op_CountedLoopEnd || iff->Opcode() == Op_LongCountedLoopEnd || iff->Opcode() == Op_RangeCheck" ") failed", "Check this code when new subtype is added"); :: breakpoint(); } } while (0); | ||||||
242 | |||||||
243 | int pop = prevdom->Opcode(); | ||||||
244 | assert( pop == Op_IfFalse || pop == Op_IfTrue, "" )do { if (!(pop == Op_IfFalse || pop == Op_IfTrue)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 244, "assert(" "pop == Op_IfFalse || pop == Op_IfTrue" ") failed" , ""); ::breakpoint(); } } while (0); | ||||||
245 | if (flip) { | ||||||
246 | if (pop == Op_IfTrue) | ||||||
247 | pop = Op_IfFalse; | ||||||
248 | else | ||||||
249 | pop = Op_IfTrue; | ||||||
250 | } | ||||||
251 | // 'con' is set to true or false to kill the dominated test. | ||||||
252 | Node *con = _igvn.makecon(pop == Op_IfTrue ? TypeInt::ONE : TypeInt::ZERO); | ||||||
253 | set_ctrl(con, C->root()); // Constant gets a new use | ||||||
254 | // Hack the dominated test | ||||||
255 | _igvn.replace_input_of(iff, 1, con); | ||||||
256 | |||||||
257 | // If I dont have a reachable TRUE and FALSE path following the IfNode then | ||||||
258 | // I can assume this path reaches an infinite loop. In this case it's not | ||||||
259 | // important to optimize the data Nodes - either the whole compilation will | ||||||
260 | // be tossed or this path (and all data Nodes) will go dead. | ||||||
261 | if (iff->outcnt() != 2) return; | ||||||
262 | |||||||
263 | // Make control-dependent data Nodes on the live path (path that will remain | ||||||
264 | // once the dominated IF is removed) become control-dependent on the | ||||||
265 | // dominating projection. | ||||||
266 | Node* dp = iff->as_If()->proj_out_or_null(pop == Op_IfTrue); | ||||||
267 | |||||||
268 | // Loop predicates may have depending checks which should not | ||||||
269 | // be skipped. For example, range check predicate has two checks | ||||||
270 | // for lower and upper bounds. | ||||||
271 | if (dp == NULL__null) | ||||||
272 | return; | ||||||
273 | |||||||
274 | ProjNode* dp_proj = dp->as_Proj(); | ||||||
275 | ProjNode* unc_proj = iff->as_If()->proj_out(1 - dp_proj->_con)->as_Proj(); | ||||||
276 | if (exclude_loop_predicate && | ||||||
277 | (unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_predicate) != NULL__null || | ||||||
278 | unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_profile_predicate) != NULL__null || | ||||||
279 | unc_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check) != NULL__null)) { | ||||||
280 | // If this is a range check (IfNode::is_range_check), do not | ||||||
281 | // reorder because Compile::allow_range_check_smearing might have | ||||||
282 | // changed the check. | ||||||
283 | return; // Let IGVN transformation change control dependence. | ||||||
284 | } | ||||||
285 | |||||||
286 | IdealLoopTree* old_loop = get_loop(dp); | ||||||
287 | |||||||
288 | for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) { | ||||||
289 | Node* cd = dp->fast_out(i); // Control-dependent node | ||||||
290 | // Do not rewire Div and Mod nodes which could have a zero divisor to avoid skipping their zero check. | ||||||
291 | if (cd->depends_only_on_test() && _igvn.no_dependent_zero_check(cd)) { | ||||||
292 | assert(cd->in(0) == dp, "")do { if (!(cd->in(0) == dp)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 292, "assert(" "cd->in(0) == dp" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
293 | _igvn.replace_input_of(cd, 0, prevdom); | ||||||
294 | set_early_ctrl(cd, false); | ||||||
295 | IdealLoopTree* new_loop = get_loop(get_ctrl(cd)); | ||||||
296 | if (old_loop != new_loop) { | ||||||
297 | if (!old_loop->_child) { | ||||||
298 | old_loop->_body.yank(cd); | ||||||
299 | } | ||||||
300 | if (!new_loop->_child) { | ||||||
301 | new_loop->_body.push(cd); | ||||||
302 | } | ||||||
303 | } | ||||||
304 | --i; | ||||||
305 | --imax; | ||||||
306 | } | ||||||
307 | } | ||||||
308 | } | ||||||
309 | |||||||
310 | //------------------------------has_local_phi_input---------------------------- | ||||||
311 | // Return TRUE if 'n' has Phi inputs from its local block and no other | ||||||
312 | // block-local inputs (all non-local-phi inputs come from earlier blocks) | ||||||
313 | Node *PhaseIdealLoop::has_local_phi_input( Node *n ) { | ||||||
314 | Node *n_ctrl = get_ctrl(n); | ||||||
315 | // See if some inputs come from a Phi in this block, or from before | ||||||
316 | // this block. | ||||||
317 | uint i; | ||||||
318 | for( i = 1; i < n->req(); i++ ) { | ||||||
319 | Node *phi = n->in(i); | ||||||
320 | if( phi->is_Phi() && phi->in(0) == n_ctrl ) | ||||||
321 | break; | ||||||
322 | } | ||||||
323 | if( i >= n->req() ) | ||||||
324 | return NULL__null; // No Phi inputs; nowhere to clone thru | ||||||
325 | |||||||
326 | // Check for inputs created between 'n' and the Phi input. These | ||||||
327 | // must split as well; they have already been given the chance | ||||||
328 | // (courtesy of a post-order visit) and since they did not we must | ||||||
329 | // recover the 'cost' of splitting them by being very profitable | ||||||
330 | // when splitting 'n'. Since this is unlikely we simply give up. | ||||||
331 | for( i = 1; i < n->req(); i++ ) { | ||||||
332 | Node *m = n->in(i); | ||||||
333 | if( get_ctrl(m) == n_ctrl && !m->is_Phi() ) { | ||||||
334 | // We allow the special case of AddP's with no local inputs. | ||||||
335 | // This allows us to split-up address expressions. | ||||||
336 | if (m->is_AddP() && | ||||||
337 | get_ctrl(m->in(2)) != n_ctrl && | ||||||
338 | get_ctrl(m->in(3)) != n_ctrl) { | ||||||
339 | // Move the AddP up to dominating point | ||||||
340 | Node* c = find_non_split_ctrl(idom(n_ctrl)); | ||||||
341 | if (c->is_OuterStripMinedLoop()) { | ||||||
342 | c->as_Loop()->verify_strip_mined(1); | ||||||
343 | c = c->in(LoopNode::EntryControl); | ||||||
344 | } | ||||||
345 | set_ctrl_and_loop(m, c); | ||||||
346 | continue; | ||||||
347 | } | ||||||
348 | return NULL__null; | ||||||
349 | } | ||||||
350 | assert(n->is_Phi() || m->is_Phi() || is_dominator(get_ctrl(m), n_ctrl), "m has strange control")do { if (!(n->is_Phi() || m->is_Phi() || is_dominator(get_ctrl (m), n_ctrl))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 350, "assert(" "n->is_Phi() || m->is_Phi() || is_dominator(get_ctrl(m), n_ctrl)" ") failed", "m has strange control"); ::breakpoint(); } } while (0); | ||||||
351 | } | ||||||
352 | |||||||
353 | return n_ctrl; | ||||||
354 | } | ||||||
355 | |||||||
356 | //------------------------------remix_address_expressions---------------------- | ||||||
357 | // Rework addressing expressions to get the most loop-invariant stuff | ||||||
358 | // moved out. We'd like to do all associative operators, but it's especially | ||||||
359 | // important (common) to do address expressions. | ||||||
360 | Node *PhaseIdealLoop::remix_address_expressions( Node *n ) { | ||||||
361 | if (!has_ctrl(n)) return NULL__null; | ||||||
362 | Node *n_ctrl = get_ctrl(n); | ||||||
363 | IdealLoopTree *n_loop = get_loop(n_ctrl); | ||||||
364 | |||||||
365 | // See if 'n' mixes loop-varying and loop-invariant inputs and | ||||||
366 | // itself is loop-varying. | ||||||
367 | |||||||
368 | // Only interested in binary ops (and AddP) | ||||||
369 | if( n->req() < 3 || n->req() > 4 ) return NULL__null; | ||||||
370 | |||||||
371 | Node *n1_ctrl = get_ctrl(n->in( 1)); | ||||||
372 | Node *n2_ctrl = get_ctrl(n->in( 2)); | ||||||
373 | Node *n3_ctrl = get_ctrl(n->in(n->req() == 3 ? 2 : 3)); | ||||||
374 | IdealLoopTree *n1_loop = get_loop( n1_ctrl ); | ||||||
375 | IdealLoopTree *n2_loop = get_loop( n2_ctrl ); | ||||||
376 | IdealLoopTree *n3_loop = get_loop( n3_ctrl ); | ||||||
377 | |||||||
378 | // Does one of my inputs spin in a tighter loop than self? | ||||||
379 | if( (n_loop->is_member( n1_loop ) && n_loop != n1_loop) || | ||||||
380 | (n_loop->is_member( n2_loop ) && n_loop != n2_loop) || | ||||||
381 | (n_loop->is_member( n3_loop ) && n_loop != n3_loop) ) | ||||||
382 | return NULL__null; // Leave well enough alone | ||||||
383 | |||||||
384 | // Is at least one of my inputs loop-invariant? | ||||||
385 | if( n1_loop == n_loop && | ||||||
386 | n2_loop == n_loop && | ||||||
387 | n3_loop == n_loop ) | ||||||
388 | return NULL__null; // No loop-invariant inputs | ||||||
389 | |||||||
390 | |||||||
391 | int n_op = n->Opcode(); | ||||||
392 | |||||||
393 | // Replace expressions like ((V+I) << 2) with (V<<2 + I<<2). | ||||||
394 | if( n_op == Op_LShiftI ) { | ||||||
395 | // Scale is loop invariant | ||||||
396 | Node *scale = n->in(2); | ||||||
397 | Node *scale_ctrl = get_ctrl(scale); | ||||||
398 | IdealLoopTree *scale_loop = get_loop(scale_ctrl ); | ||||||
399 | if( n_loop == scale_loop || !scale_loop->is_member( n_loop ) ) | ||||||
400 | return NULL__null; | ||||||
401 | const TypeInt *scale_t = scale->bottom_type()->isa_int(); | ||||||
402 | if( scale_t && scale_t->is_con() && scale_t->get_con() >= 16 ) | ||||||
403 | return NULL__null; // Dont bother with byte/short masking | ||||||
404 | // Add must vary with loop (else shift would be loop-invariant) | ||||||
405 | Node *add = n->in(1); | ||||||
406 | Node *add_ctrl = get_ctrl(add); | ||||||
407 | IdealLoopTree *add_loop = get_loop(add_ctrl); | ||||||
408 | //assert( n_loop == add_loop, "" ); | ||||||
409 | if( n_loop != add_loop ) return NULL__null; // happens w/ evil ZKM loops | ||||||
410 | |||||||
411 | // Convert I-V into I+ (0-V); same for V-I | ||||||
412 | if( add->Opcode() == Op_SubI && | ||||||
413 | _igvn.type( add->in(1) ) != TypeInt::ZERO ) { | ||||||
414 | Node *zero = _igvn.intcon(0); | ||||||
415 | set_ctrl(zero, C->root()); | ||||||
416 | Node *neg = new SubINode( _igvn.intcon(0), add->in(2) ); | ||||||
417 | register_new_node( neg, get_ctrl(add->in(2) ) ); | ||||||
418 | add = new AddINode( add->in(1), neg ); | ||||||
419 | register_new_node( add, add_ctrl ); | ||||||
420 | } | ||||||
421 | if( add->Opcode() != Op_AddI ) return NULL__null; | ||||||
422 | // See if one add input is loop invariant | ||||||
423 | Node *add_var = add->in(1); | ||||||
424 | Node *add_var_ctrl = get_ctrl(add_var); | ||||||
425 | IdealLoopTree *add_var_loop = get_loop(add_var_ctrl ); | ||||||
426 | Node *add_invar = add->in(2); | ||||||
427 | Node *add_invar_ctrl = get_ctrl(add_invar); | ||||||
428 | IdealLoopTree *add_invar_loop = get_loop(add_invar_ctrl ); | ||||||
429 | if( add_var_loop == n_loop ) { | ||||||
430 | } else if( add_invar_loop == n_loop ) { | ||||||
431 | // Swap to find the invariant part | ||||||
432 | add_invar = add_var; | ||||||
433 | add_invar_ctrl = add_var_ctrl; | ||||||
434 | add_invar_loop = add_var_loop; | ||||||
435 | add_var = add->in(2); | ||||||
436 | Node *add_var_ctrl = get_ctrl(add_var); | ||||||
437 | IdealLoopTree *add_var_loop = get_loop(add_var_ctrl ); | ||||||
438 | } else // Else neither input is loop invariant | ||||||
439 | return NULL__null; | ||||||
440 | if( n_loop == add_invar_loop || !add_invar_loop->is_member( n_loop ) ) | ||||||
441 | return NULL__null; // No invariant part of the add? | ||||||
442 | |||||||
443 | // Yes! Reshape address expression! | ||||||
444 | Node *inv_scale = new LShiftINode( add_invar, scale ); | ||||||
445 | Node *inv_scale_ctrl = | ||||||
446 | dom_depth(add_invar_ctrl) > dom_depth(scale_ctrl) ? | ||||||
447 | add_invar_ctrl : scale_ctrl; | ||||||
448 | register_new_node( inv_scale, inv_scale_ctrl ); | ||||||
449 | Node *var_scale = new LShiftINode( add_var, scale ); | ||||||
450 | register_new_node( var_scale, n_ctrl ); | ||||||
451 | Node *var_add = new AddINode( var_scale, inv_scale ); | ||||||
452 | register_new_node( var_add, n_ctrl ); | ||||||
453 | _igvn.replace_node( n, var_add ); | ||||||
454 | return var_add; | ||||||
455 | } | ||||||
456 | |||||||
457 | // Replace (I+V) with (V+I) | ||||||
458 | if( n_op == Op_AddI || | ||||||
459 | n_op == Op_AddL || | ||||||
460 | n_op == Op_AddF || | ||||||
461 | n_op == Op_AddD || | ||||||
462 | n_op == Op_MulI || | ||||||
463 | n_op == Op_MulL || | ||||||
464 | n_op == Op_MulF || | ||||||
465 | n_op == Op_MulD ) { | ||||||
466 | if( n2_loop == n_loop ) { | ||||||
467 | assert( n1_loop != n_loop, "" )do { if (!(n1_loop != n_loop)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 467, "assert(" "n1_loop != n_loop" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
468 | n->swap_edges(1, 2); | ||||||
469 | } | ||||||
470 | } | ||||||
471 | |||||||
472 | // Replace ((I1 +p V) +p I2) with ((I1 +p I2) +p V), | ||||||
473 | // but not if I2 is a constant. | ||||||
474 | if( n_op == Op_AddP ) { | ||||||
475 | if( n2_loop == n_loop && n3_loop != n_loop ) { | ||||||
476 | if( n->in(2)->Opcode() == Op_AddP && !n->in(3)->is_Con() ) { | ||||||
477 | Node *n22_ctrl = get_ctrl(n->in(2)->in(2)); | ||||||
478 | Node *n23_ctrl = get_ctrl(n->in(2)->in(3)); | ||||||
479 | IdealLoopTree *n22loop = get_loop( n22_ctrl ); | ||||||
480 | IdealLoopTree *n23_loop = get_loop( n23_ctrl ); | ||||||
481 | if( n22loop != n_loop && n22loop->is_member(n_loop) && | ||||||
482 | n23_loop == n_loop ) { | ||||||
483 | Node *add1 = new AddPNode( n->in(1), n->in(2)->in(2), n->in(3) ); | ||||||
484 | // Stuff new AddP in the loop preheader | ||||||
485 | register_new_node( add1, n_loop->_head->in(LoopNode::EntryControl) ); | ||||||
486 | Node *add2 = new AddPNode( n->in(1), add1, n->in(2)->in(3) ); | ||||||
487 | register_new_node( add2, n_ctrl ); | ||||||
488 | _igvn.replace_node( n, add2 ); | ||||||
489 | return add2; | ||||||
490 | } | ||||||
491 | } | ||||||
492 | } | ||||||
493 | |||||||
494 | // Replace (I1 +p (I2 + V)) with ((I1 +p I2) +p V) | ||||||
495 | if (n2_loop != n_loop && n3_loop == n_loop) { | ||||||
496 | if (n->in(3)->Opcode() == Op_AddXOp_AddL) { | ||||||
497 | Node *V = n->in(3)->in(1); | ||||||
498 | Node *I = n->in(3)->in(2); | ||||||
499 | if (is_member(n_loop,get_ctrl(V))) { | ||||||
500 | } else { | ||||||
501 | Node *tmp = V; V = I; I = tmp; | ||||||
502 | } | ||||||
503 | if (!is_member(n_loop,get_ctrl(I))) { | ||||||
504 | Node *add1 = new AddPNode(n->in(1), n->in(2), I); | ||||||
505 | // Stuff new AddP in the loop preheader | ||||||
506 | register_new_node(add1, n_loop->_head->in(LoopNode::EntryControl)); | ||||||
507 | Node *add2 = new AddPNode(n->in(1), add1, V); | ||||||
508 | register_new_node(add2, n_ctrl); | ||||||
509 | _igvn.replace_node(n, add2); | ||||||
510 | return add2; | ||||||
511 | } | ||||||
512 | } | ||||||
513 | } | ||||||
514 | } | ||||||
515 | |||||||
516 | return NULL__null; | ||||||
517 | } | ||||||
518 | |||||||
519 | // Optimize ((in1[2*i] * in2[2*i]) + (in1[2*i+1] * in2[2*i+1])) | ||||||
520 | Node *PhaseIdealLoop::convert_add_to_muladd(Node* n) { | ||||||
521 | assert(n->Opcode() == Op_AddI, "sanity")do { if (!(n->Opcode() == Op_AddI)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 521, "assert(" "n->Opcode() == Op_AddI" ") failed", "sanity" ); ::breakpoint(); } } while (0); | ||||||
522 | Node * nn = NULL__null; | ||||||
523 | Node * in1 = n->in(1); | ||||||
524 | Node * in2 = n->in(2); | ||||||
525 | if (in1->Opcode() == Op_MulI && in2->Opcode() == Op_MulI) { | ||||||
526 | IdealLoopTree* loop_n = get_loop(get_ctrl(n)); | ||||||
527 | if (loop_n->is_counted() && | ||||||
528 | loop_n->_head->as_Loop()->is_valid_counted_loop(T_INT) && | ||||||
529 | Matcher::match_rule_supported(Op_MulAddVS2VI) && | ||||||
530 | Matcher::match_rule_supported(Op_MulAddS2I)) { | ||||||
531 | Node* mul_in1 = in1->in(1); | ||||||
532 | Node* mul_in2 = in1->in(2); | ||||||
533 | Node* mul_in3 = in2->in(1); | ||||||
534 | Node* mul_in4 = in2->in(2); | ||||||
535 | if (mul_in1->Opcode() == Op_LoadS && | ||||||
536 | mul_in2->Opcode() == Op_LoadS && | ||||||
537 | mul_in3->Opcode() == Op_LoadS && | ||||||
538 | mul_in4->Opcode() == Op_LoadS) { | ||||||
539 | IdealLoopTree* loop1 = get_loop(get_ctrl(mul_in1)); | ||||||
540 | IdealLoopTree* loop2 = get_loop(get_ctrl(mul_in2)); | ||||||
541 | IdealLoopTree* loop3 = get_loop(get_ctrl(mul_in3)); | ||||||
542 | IdealLoopTree* loop4 = get_loop(get_ctrl(mul_in4)); | ||||||
543 | IdealLoopTree* loop5 = get_loop(get_ctrl(in1)); | ||||||
544 | IdealLoopTree* loop6 = get_loop(get_ctrl(in2)); | ||||||
545 | // All nodes should be in the same counted loop. | ||||||
546 | if (loop_n == loop1 && loop_n == loop2 && loop_n == loop3 && | ||||||
547 | loop_n == loop4 && loop_n == loop5 && loop_n == loop6) { | ||||||
548 | Node* adr1 = mul_in1->in(MemNode::Address); | ||||||
549 | Node* adr2 = mul_in2->in(MemNode::Address); | ||||||
550 | Node* adr3 = mul_in3->in(MemNode::Address); | ||||||
551 | Node* adr4 = mul_in4->in(MemNode::Address); | ||||||
552 | if (adr1->is_AddP() && adr2->is_AddP() && adr3->is_AddP() && adr4->is_AddP()) { | ||||||
553 | if ((adr1->in(AddPNode::Base) == adr3->in(AddPNode::Base)) && | ||||||
554 | (adr2->in(AddPNode::Base) == adr4->in(AddPNode::Base))) { | ||||||
555 | nn = new MulAddS2INode(mul_in1, mul_in2, mul_in3, mul_in4); | ||||||
556 | register_new_node(nn, get_ctrl(n)); | ||||||
557 | _igvn.replace_node(n, nn); | ||||||
558 | return nn; | ||||||
559 | } else if ((adr1->in(AddPNode::Base) == adr4->in(AddPNode::Base)) && | ||||||
560 | (adr2->in(AddPNode::Base) == adr3->in(AddPNode::Base))) { | ||||||
561 | nn = new MulAddS2INode(mul_in1, mul_in2, mul_in4, mul_in3); | ||||||
562 | register_new_node(nn, get_ctrl(n)); | ||||||
563 | _igvn.replace_node(n, nn); | ||||||
564 | return nn; | ||||||
565 | } | ||||||
566 | } | ||||||
567 | } | ||||||
568 | } | ||||||
569 | } | ||||||
570 | } | ||||||
571 | return nn; | ||||||
572 | } | ||||||
573 | |||||||
574 | //------------------------------conditional_move------------------------------- | ||||||
575 | // Attempt to replace a Phi with a conditional move. We have some pretty | ||||||
576 | // strict profitability requirements. All Phis at the merge point must | ||||||
577 | // be converted, so we can remove the control flow. We need to limit the | ||||||
578 | // number of c-moves to a small handful. All code that was in the side-arms | ||||||
579 | // of the CFG diamond is now speculatively executed. This code has to be | ||||||
580 | // "cheap enough". We are pretty much limited to CFG diamonds that merge | ||||||
581 | // 1 or 2 items with a total of 1 or 2 ops executed speculatively. | ||||||
582 | Node *PhaseIdealLoop::conditional_move( Node *region ) { | ||||||
583 | |||||||
584 | assert(region->is_Region(), "sanity check")do { if (!(region->is_Region())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 584, "assert(" "region->is_Region()" ") failed", "sanity check" ); ::breakpoint(); } } while (0); | ||||||
585 | if (region->req() != 3) return NULL__null; | ||||||
586 | |||||||
587 | // Check for CFG diamond | ||||||
588 | Node *lp = region->in(1); | ||||||
589 | Node *rp = region->in(2); | ||||||
590 | if (!lp || !rp) return NULL__null; | ||||||
591 | Node *lp_c = lp->in(0); | ||||||
592 | if (lp_c == NULL__null || lp_c != rp->in(0) || !lp_c->is_If()) return NULL__null; | ||||||
593 | IfNode *iff = lp_c->as_If(); | ||||||
594 | |||||||
595 | // Check for ops pinned in an arm of the diamond. | ||||||
596 | // Can't remove the control flow in this case | ||||||
597 | if (lp->outcnt() > 1) return NULL__null; | ||||||
598 | if (rp->outcnt() > 1) return NULL__null; | ||||||
599 | |||||||
600 | IdealLoopTree* r_loop = get_loop(region); | ||||||
601 | assert(r_loop == get_loop(iff), "sanity")do { if (!(r_loop == get_loop(iff))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 601, "assert(" "r_loop == get_loop(iff)" ") failed", "sanity" ); ::breakpoint(); } } while (0); | ||||||
602 | // Always convert to CMOVE if all results are used only outside this loop. | ||||||
603 | bool used_inside_loop = (r_loop == _ltree_root); | ||||||
604 | |||||||
605 | // Check profitability | ||||||
606 | int cost = 0; | ||||||
607 | int phis = 0; | ||||||
608 | for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { | ||||||
609 | Node *out = region->fast_out(i); | ||||||
610 | if (!out->is_Phi()) continue; // Ignore other control edges, etc | ||||||
611 | phis++; | ||||||
612 | PhiNode* phi = out->as_Phi(); | ||||||
613 | BasicType bt = phi->type()->basic_type(); | ||||||
614 | switch (bt) { | ||||||
615 | case T_DOUBLE: | ||||||
616 | case T_FLOAT: | ||||||
617 | if (C->use_cmove()) { | ||||||
618 | continue; //TODO: maybe we want to add some cost | ||||||
619 | } | ||||||
620 | cost += Matcher::float_cmove_cost(); // Could be very expensive | ||||||
621 | break; | ||||||
622 | case T_LONG: { | ||||||
623 | cost += Matcher::long_cmove_cost(); // May encodes as 2 CMOV's | ||||||
624 | } | ||||||
625 | case T_INT: // These all CMOV fine | ||||||
626 | case T_ADDRESS: { // (RawPtr) | ||||||
627 | cost++; | ||||||
628 | break; | ||||||
629 | } | ||||||
630 | case T_NARROWOOP: // Fall through | ||||||
631 | case T_OBJECT: { // Base oops are OK, but not derived oops | ||||||
632 | const TypeOopPtr *tp = phi->type()->make_ptr()->isa_oopptr(); | ||||||
633 | // Derived pointers are Bad (tm): what's the Base (for GC purposes) of a | ||||||
634 | // CMOVE'd derived pointer? It's a CMOVE'd derived base. Thus | ||||||
635 | // CMOVE'ing a derived pointer requires we also CMOVE the base. If we | ||||||
636 | // have a Phi for the base here that we convert to a CMOVE all is well | ||||||
637 | // and good. But if the base is dead, we'll not make a CMOVE. Later | ||||||
638 | // the allocator will have to produce a base by creating a CMOVE of the | ||||||
639 | // relevant bases. This puts the allocator in the business of | ||||||
640 | // manufacturing expensive instructions, generally a bad plan. | ||||||
641 | // Just Say No to Conditionally-Moved Derived Pointers. | ||||||
642 | if (tp && tp->offset() != 0) | ||||||
643 | return NULL__null; | ||||||
644 | cost++; | ||||||
645 | break; | ||||||
646 | } | ||||||
647 | default: | ||||||
648 | return NULL__null; // In particular, can't do memory or I/O | ||||||
649 | } | ||||||
650 | // Add in cost any speculative ops | ||||||
651 | for (uint j = 1; j < region->req(); j++) { | ||||||
652 | Node *proj = region->in(j); | ||||||
653 | Node *inp = phi->in(j); | ||||||
654 | if (get_ctrl(inp) == proj) { // Found local op | ||||||
655 | cost++; | ||||||
656 | // Check for a chain of dependent ops; these will all become | ||||||
657 | // speculative in a CMOV. | ||||||
658 | for (uint k = 1; k < inp->req(); k++) | ||||||
659 | if (get_ctrl(inp->in(k)) == proj) | ||||||
660 | cost += ConditionalMoveLimit; // Too much speculative goo | ||||||
661 | } | ||||||
662 | } | ||||||
663 | // See if the Phi is used by a Cmp or Narrow oop Decode/Encode. | ||||||
664 | // This will likely Split-If, a higher-payoff operation. | ||||||
665 | for (DUIterator_Fast kmax, k = phi->fast_outs(kmax); k < kmax; k++) { | ||||||
666 | Node* use = phi->fast_out(k); | ||||||
667 | if (use->is_Cmp() || use->is_DecodeNarrowPtr() || use->is_EncodeNarrowPtr()) | ||||||
668 | cost += ConditionalMoveLimit; | ||||||
669 | // Is there a use inside the loop? | ||||||
670 | // Note: check only basic types since CMoveP is pinned. | ||||||
671 | if (!used_inside_loop && is_java_primitive(bt)) { | ||||||
672 | IdealLoopTree* u_loop = get_loop(has_ctrl(use) ? get_ctrl(use) : use); | ||||||
673 | if (r_loop == u_loop || r_loop->is_member(u_loop)) { | ||||||
674 | used_inside_loop = true; | ||||||
675 | } | ||||||
676 | } | ||||||
677 | } | ||||||
678 | }//for | ||||||
679 | Node* bol = iff->in(1); | ||||||
680 | if (bol->Opcode() == Op_Opaque4) { | ||||||
681 | return NULL__null; // Ignore loop predicate checks (the Opaque4 ensures they will go away) | ||||||
682 | } | ||||||
683 | assert(bol->Opcode() == Op_Bool, "Unexpected node")do { if (!(bol->Opcode() == Op_Bool)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 683, "assert(" "bol->Opcode() == Op_Bool" ") failed", "Unexpected node" ); ::breakpoint(); } } while (0); | ||||||
684 | int cmp_op = bol->in(1)->Opcode(); | ||||||
685 | if (cmp_op == Op_SubTypeCheck) { // SubTypeCheck expansion expects an IfNode | ||||||
686 | return NULL__null; | ||||||
687 | } | ||||||
688 | // It is expensive to generate flags from a float compare. | ||||||
689 | // Avoid duplicated float compare. | ||||||
690 | if (phis > 1 && (cmp_op == Op_CmpF || cmp_op == Op_CmpD)) return NULL__null; | ||||||
691 | |||||||
692 | float infrequent_prob = PROB_UNLIKELY_MAG(3)(1e-3f); | ||||||
693 | // Ignore cost and blocks frequency if CMOVE can be moved outside the loop. | ||||||
694 | if (used_inside_loop) { | ||||||
695 | if (cost >= ConditionalMoveLimit) return NULL__null; // Too much goo | ||||||
696 | |||||||
697 | // BlockLayoutByFrequency optimization moves infrequent branch | ||||||
698 | // from hot path. No point in CMOV'ing in such case (110 is used | ||||||
699 | // instead of 100 to take into account not exactness of float value). | ||||||
700 | if (BlockLayoutByFrequency) { | ||||||
701 | infrequent_prob = MAX2(infrequent_prob, (float)BlockLayoutMinDiamondPercentage/110.0f); | ||||||
702 | } | ||||||
703 | } | ||||||
704 | // Check for highly predictable branch. No point in CMOV'ing if | ||||||
705 | // we are going to predict accurately all the time. | ||||||
706 | if (C->use_cmove() && (cmp_op == Op_CmpF || cmp_op == Op_CmpD)) { | ||||||
707 | //keep going | ||||||
708 | } else if (iff->_prob < infrequent_prob || | ||||||
709 | iff->_prob > (1.0f - infrequent_prob)) | ||||||
710 | return NULL__null; | ||||||
711 | |||||||
712 | // -------------- | ||||||
713 | // Now replace all Phis with CMOV's | ||||||
714 | Node *cmov_ctrl = iff->in(0); | ||||||
715 | uint flip = (lp->Opcode() == Op_IfTrue); | ||||||
716 | Node_List wq; | ||||||
717 | while (1) { | ||||||
718 | PhiNode* phi = NULL__null; | ||||||
719 | for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { | ||||||
720 | Node *out = region->fast_out(i); | ||||||
721 | if (out->is_Phi()) { | ||||||
722 | phi = out->as_Phi(); | ||||||
723 | break; | ||||||
724 | } | ||||||
725 | } | ||||||
726 | if (phi == NULL__null || _igvn.type(phi) == Type::TOP) { | ||||||
727 | break; | ||||||
728 | } | ||||||
729 | if (PrintOpto && VerifyLoopOptimizations) { tty->print_cr("CMOV"); } | ||||||
730 | // Move speculative ops | ||||||
731 | wq.push(phi); | ||||||
732 | while (wq.size() > 0) { | ||||||
733 | Node *n = wq.pop(); | ||||||
734 | for (uint j = 1; j < n->req(); j++) { | ||||||
735 | Node* m = n->in(j); | ||||||
736 | if (m != NULL__null && !is_dominator(get_ctrl(m), cmov_ctrl)) { | ||||||
737 | #ifndef PRODUCT | ||||||
738 | if (PrintOpto && VerifyLoopOptimizations) { | ||||||
739 | tty->print(" speculate: "); | ||||||
740 | m->dump(); | ||||||
741 | } | ||||||
742 | #endif | ||||||
743 | set_ctrl(m, cmov_ctrl); | ||||||
744 | wq.push(m); | ||||||
745 | } | ||||||
746 | } | ||||||
747 | } | ||||||
748 | Node *cmov = CMoveNode::make(cmov_ctrl, iff->in(1), phi->in(1+flip), phi->in(2-flip), _igvn.type(phi)); | ||||||
749 | register_new_node( cmov, cmov_ctrl ); | ||||||
750 | _igvn.replace_node( phi, cmov ); | ||||||
751 | #ifndef PRODUCT | ||||||
752 | if (TraceLoopOpts) { | ||||||
753 | tty->print("CMOV "); | ||||||
754 | r_loop->dump_head(); | ||||||
755 | if (Verbose) { | ||||||
756 | bol->in(1)->dump(1); | ||||||
757 | cmov->dump(1); | ||||||
758 | } | ||||||
759 | } | ||||||
760 | if (VerifyLoopOptimizations) verify(); | ||||||
761 | #endif | ||||||
762 | } | ||||||
763 | |||||||
764 | // The useless CFG diamond will fold up later; see the optimization in | ||||||
765 | // RegionNode::Ideal. | ||||||
766 | _igvn._worklist.push(region); | ||||||
767 | |||||||
768 | return iff->in(1); | ||||||
769 | } | ||||||
770 | |||||||
771 | static void enqueue_cfg_uses(Node* m, Unique_Node_List& wq) { | ||||||
772 | for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { | ||||||
773 | Node* u = m->fast_out(i); | ||||||
774 | if (u->is_CFG()) { | ||||||
775 | if (u->Opcode() == Op_NeverBranch) { | ||||||
776 | u = ((NeverBranchNode*)u)->proj_out(0); | ||||||
777 | enqueue_cfg_uses(u, wq); | ||||||
778 | } else { | ||||||
779 | wq.push(u); | ||||||
780 | } | ||||||
781 | } | ||||||
782 | } | ||||||
783 | } | ||||||
784 | |||||||
785 | // Try moving a store out of a loop, right before the loop | ||||||
786 | Node* PhaseIdealLoop::try_move_store_before_loop(Node* n, Node *n_ctrl) { | ||||||
787 | // Store has to be first in the loop body | ||||||
788 | IdealLoopTree *n_loop = get_loop(n_ctrl); | ||||||
789 | if (n->is_Store() && n_loop != _ltree_root && | ||||||
790 | n_loop->is_loop() && n_loop->_head->is_Loop() && | ||||||
791 | n->in(0) != NULL__null) { | ||||||
792 | Node* address = n->in(MemNode::Address); | ||||||
793 | Node* value = n->in(MemNode::ValueIn); | ||||||
794 | Node* mem = n->in(MemNode::Memory); | ||||||
795 | IdealLoopTree* address_loop = get_loop(get_ctrl(address)); | ||||||
796 | IdealLoopTree* value_loop = get_loop(get_ctrl(value)); | ||||||
797 | |||||||
798 | // - address and value must be loop invariant | ||||||
799 | // - memory must be a memory Phi for the loop | ||||||
800 | // - Store must be the only store on this memory slice in the | ||||||
801 | // loop: if there's another store following this one then value | ||||||
802 | // written at iteration i by the second store could be overwritten | ||||||
803 | // at iteration i+n by the first store: it's not safe to move the | ||||||
804 | // first store out of the loop | ||||||
805 | // - nothing must observe the memory Phi: it guarantees no read | ||||||
806 | // before the store, we are also guaranteed the store post | ||||||
807 | // dominates the loop head (ignoring a possible early | ||||||
808 | // exit). Otherwise there would be extra Phi involved between the | ||||||
809 | // loop's Phi and the store. | ||||||
810 | // - there must be no early exit from the loop before the Store | ||||||
811 | // (such an exit most of the time would be an extra use of the | ||||||
812 | // memory Phi but sometimes is a bottom memory Phi that takes the | ||||||
813 | // store as input). | ||||||
814 | |||||||
815 | if (!n_loop->is_member(address_loop) && | ||||||
816 | !n_loop->is_member(value_loop) && | ||||||
817 | mem->is_Phi() && mem->in(0) == n_loop->_head && | ||||||
818 | mem->outcnt() == 1 && | ||||||
819 | mem->in(LoopNode::LoopBackControl) == n) { | ||||||
820 | |||||||
821 | assert(n_loop->_tail != NULL, "need a tail")do { if (!(n_loop->_tail != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 821, "assert(" "n_loop->_tail != __null" ") failed", "need a tail" ); ::breakpoint(); } } while (0); | ||||||
822 | assert(is_dominator(n_ctrl, n_loop->_tail), "store control must not be in a branch in the loop")do { if (!(is_dominator(n_ctrl, n_loop->_tail))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 822, "assert(" "is_dominator(n_ctrl, n_loop->_tail)" ") failed" , "store control must not be in a branch in the loop"); ::breakpoint (); } } while (0); | ||||||
823 | |||||||
824 | // Verify that there's no early exit of the loop before the store. | ||||||
825 | bool ctrl_ok = false; | ||||||
826 | { | ||||||
827 | // Follow control from loop head until n, we exit the loop or | ||||||
828 | // we reach the tail | ||||||
829 | ResourceMark rm; | ||||||
830 | Unique_Node_List wq; | ||||||
831 | wq.push(n_loop->_head); | ||||||
832 | |||||||
833 | for (uint next = 0; next < wq.size(); ++next) { | ||||||
834 | Node *m = wq.at(next); | ||||||
835 | if (m == n->in(0)) { | ||||||
836 | ctrl_ok = true; | ||||||
837 | continue; | ||||||
838 | } | ||||||
839 | assert(!has_ctrl(m), "should be CFG")do { if (!(!has_ctrl(m))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 839, "assert(" "!has_ctrl(m)" ") failed", "should be CFG"); ::breakpoint(); } } while (0); | ||||||
840 | if (!n_loop->is_member(get_loop(m)) || m == n_loop->_tail) { | ||||||
841 | ctrl_ok = false; | ||||||
842 | break; | ||||||
843 | } | ||||||
844 | enqueue_cfg_uses(m, wq); | ||||||
845 | if (wq.size() > 10) { | ||||||
846 | ctrl_ok = false; | ||||||
847 | break; | ||||||
848 | } | ||||||
849 | } | ||||||
850 | } | ||||||
851 | if (ctrl_ok) { | ||||||
852 | // move the Store | ||||||
853 | _igvn.replace_input_of(mem, LoopNode::LoopBackControl, mem); | ||||||
854 | _igvn.replace_input_of(n, 0, n_loop->_head->as_Loop()->skip_strip_mined()->in(LoopNode::EntryControl)); | ||||||
855 | _igvn.replace_input_of(n, MemNode::Memory, mem->in(LoopNode::EntryControl)); | ||||||
856 | // Disconnect the phi now. An empty phi can confuse other | ||||||
857 | // optimizations in this pass of loop opts. | ||||||
858 | _igvn.replace_node(mem, mem->in(LoopNode::EntryControl)); | ||||||
859 | n_loop->_body.yank(mem); | ||||||
860 | |||||||
861 | set_ctrl_and_loop(n, n->in(0)); | ||||||
862 | |||||||
863 | return n; | ||||||
864 | } | ||||||
865 | } | ||||||
866 | } | ||||||
867 | return NULL__null; | ||||||
868 | } | ||||||
869 | |||||||
870 | // Try moving a store out of a loop, right after the loop | ||||||
871 | void PhaseIdealLoop::try_move_store_after_loop(Node* n) { | ||||||
872 | if (n->is_Store() && n->in(0) != NULL__null) { | ||||||
873 | Node *n_ctrl = get_ctrl(n); | ||||||
874 | IdealLoopTree *n_loop = get_loop(n_ctrl); | ||||||
875 | // Store must be in a loop | ||||||
876 | if (n_loop != _ltree_root && !n_loop->_irreducible) { | ||||||
877 | Node* address = n->in(MemNode::Address); | ||||||
878 | Node* value = n->in(MemNode::ValueIn); | ||||||
879 | IdealLoopTree* address_loop = get_loop(get_ctrl(address)); | ||||||
880 | // address must be loop invariant | ||||||
881 | if (!n_loop->is_member(address_loop)) { | ||||||
882 | // Store must be last on this memory slice in the loop and | ||||||
883 | // nothing in the loop must observe it | ||||||
884 | Node* phi = NULL__null; | ||||||
885 | for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { | ||||||
886 | Node* u = n->fast_out(i); | ||||||
887 | if (has_ctrl(u)) { // control use? | ||||||
888 | IdealLoopTree *u_loop = get_loop(get_ctrl(u)); | ||||||
889 | if (!n_loop->is_member(u_loop)) { | ||||||
890 | continue; | ||||||
891 | } | ||||||
892 | if (u->is_Phi() && u->in(0) == n_loop->_head) { | ||||||
893 | assert(_igvn.type(u) == Type::MEMORY, "bad phi")do { if (!(_igvn.type(u) == Type::MEMORY)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 893, "assert(" "_igvn.type(u) == Type::MEMORY" ") failed", "bad phi" ); ::breakpoint(); } } while (0); | ||||||
894 | // multiple phis on the same slice are possible | ||||||
895 | if (phi != NULL__null) { | ||||||
896 | return; | ||||||
897 | } | ||||||
898 | phi = u; | ||||||
899 | continue; | ||||||
900 | } | ||||||
901 | } | ||||||
902 | return; | ||||||
903 | } | ||||||
904 | if (phi != NULL__null) { | ||||||
905 | // Nothing in the loop before the store (next iteration) | ||||||
906 | // must observe the stored value | ||||||
907 | bool mem_ok = true; | ||||||
908 | { | ||||||
909 | ResourceMark rm; | ||||||
910 | Unique_Node_List wq; | ||||||
911 | wq.push(phi); | ||||||
912 | for (uint next = 0; next < wq.size() && mem_ok; ++next) { | ||||||
913 | Node *m = wq.at(next); | ||||||
914 | for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax && mem_ok; i++) { | ||||||
915 | Node* u = m->fast_out(i); | ||||||
916 | if (u->is_Store() || u->is_Phi()) { | ||||||
917 | if (u != n) { | ||||||
918 | wq.push(u); | ||||||
919 | mem_ok = (wq.size() <= 10); | ||||||
920 | } | ||||||
921 | } else { | ||||||
922 | mem_ok = false; | ||||||
923 | break; | ||||||
924 | } | ||||||
925 | } | ||||||
926 | } | ||||||
927 | } | ||||||
928 | if (mem_ok) { | ||||||
929 | // Move the store out of the loop if the LCA of all | ||||||
930 | // users (except for the phi) is outside the loop. | ||||||
931 | Node* hook = new Node(1); | ||||||
932 | hook->init_req(0, n_ctrl); // Add an input to prevent hook from being dead | ||||||
933 | _igvn.rehash_node_delayed(phi); | ||||||
934 | int count = phi->replace_edge(n, hook, &_igvn); | ||||||
935 | assert(count > 0, "inconsistent phi")do { if (!(count > 0)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 935, "assert(" "count > 0" ") failed", "inconsistent phi" ); ::breakpoint(); } } while (0); | ||||||
936 | |||||||
937 | // Compute latest point this store can go | ||||||
938 | Node* lca = get_late_ctrl(n, get_ctrl(n)); | ||||||
939 | if (lca->is_OuterStripMinedLoop()) { | ||||||
940 | lca = lca->in(LoopNode::EntryControl); | ||||||
941 | } | ||||||
942 | if (n_loop->is_member(get_loop(lca))) { | ||||||
943 | // LCA is in the loop - bail out | ||||||
944 | _igvn.replace_node(hook, n); | ||||||
945 | return; | ||||||
946 | } | ||||||
947 | #ifdef ASSERT1 | ||||||
948 | if (n_loop->_head->is_Loop() && n_loop->_head->as_Loop()->is_strip_mined()) { | ||||||
949 | assert(n_loop->_head->Opcode() == Op_CountedLoop, "outer loop is a strip mined")do { if (!(n_loop->_head->Opcode() == Op_CountedLoop)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 949, "assert(" "n_loop->_head->Opcode() == Op_CountedLoop" ") failed", "outer loop is a strip mined"); ::breakpoint(); } } while (0); | ||||||
950 | n_loop->_head->as_Loop()->verify_strip_mined(1); | ||||||
951 | Node* outer = n_loop->_head->as_CountedLoop()->outer_loop(); | ||||||
952 | IdealLoopTree* outer_loop = get_loop(outer); | ||||||
953 | assert(n_loop->_parent == outer_loop, "broken loop tree")do { if (!(n_loop->_parent == outer_loop)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 953, "assert(" "n_loop->_parent == outer_loop" ") failed" , "broken loop tree"); ::breakpoint(); } } while (0); | ||||||
954 | assert(get_loop(lca) == outer_loop, "safepoint in outer loop consume all memory state")do { if (!(get_loop(lca) == outer_loop)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 954, "assert(" "get_loop(lca) == outer_loop" ") failed", "safepoint in outer loop consume all memory state" ); ::breakpoint(); } } while (0); | ||||||
955 | } | ||||||
956 | #endif | ||||||
957 | lca = place_outside_loop(lca, n_loop); | ||||||
958 | assert(!n_loop->is_member(get_loop(lca)), "control must not be back in the loop")do { if (!(!n_loop->is_member(get_loop(lca)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 958, "assert(" "!n_loop->is_member(get_loop(lca))" ") failed" , "control must not be back in the loop"); ::breakpoint(); } } while (0); | ||||||
959 | assert(get_loop(lca)->_nest < n_loop->_nest || lca->in(0)->Opcode() == Op_NeverBranch, "must not be moved into inner loop")do { if (!(get_loop(lca)->_nest < n_loop->_nest || lca ->in(0)->Opcode() == Op_NeverBranch)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 959, "assert(" "get_loop(lca)->_nest < n_loop->_nest || lca->in(0)->Opcode() == Op_NeverBranch" ") failed", "must not be moved into inner loop"); ::breakpoint (); } } while (0); | ||||||
960 | |||||||
961 | // Move store out of the loop | ||||||
962 | _igvn.replace_node(hook, n->in(MemNode::Memory)); | ||||||
963 | _igvn.replace_input_of(n, 0, lca); | ||||||
964 | set_ctrl_and_loop(n, lca); | ||||||
965 | |||||||
966 | // Disconnect the phi now. An empty phi can confuse other | ||||||
967 | // optimizations in this pass of loop opts.. | ||||||
968 | if (phi->in(LoopNode::LoopBackControl) == phi) { | ||||||
969 | _igvn.replace_node(phi, phi->in(LoopNode::EntryControl)); | ||||||
970 | n_loop->_body.yank(phi); | ||||||
971 | } | ||||||
972 | } | ||||||
973 | } | ||||||
974 | } | ||||||
975 | } | ||||||
976 | } | ||||||
977 | } | ||||||
978 | |||||||
979 | //------------------------------split_if_with_blocks_pre----------------------- | ||||||
980 | // Do the real work in a non-recursive function. Data nodes want to be | ||||||
981 | // cloned in the pre-order so they can feed each other nicely. | ||||||
982 | Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) { | ||||||
983 | // Cloning these guys is unlikely to win | ||||||
984 | int n_op = n->Opcode(); | ||||||
985 | if (n_op == Op_MergeMem) { | ||||||
986 | return n; | ||||||
987 | } | ||||||
988 | if (n->is_Proj()) { | ||||||
989 | return n; | ||||||
990 | } | ||||||
991 | // Do not clone-up CmpFXXX variations, as these are always | ||||||
992 | // followed by a CmpI | ||||||
993 | if (n->is_Cmp()) { | ||||||
994 | return n; | ||||||
995 | } | ||||||
996 | // Attempt to use a conditional move instead of a phi/branch | ||||||
997 | if (ConditionalMoveLimit > 0 && n_op == Op_Region) { | ||||||
998 | Node *cmov = conditional_move( n ); | ||||||
999 | if (cmov) { | ||||||
1000 | return cmov; | ||||||
1001 | } | ||||||
1002 | } | ||||||
1003 | if (n->is_CFG() || n->is_LoadStore()) { | ||||||
1004 | return n; | ||||||
1005 | } | ||||||
1006 | if (n->is_Opaque1() || // Opaque nodes cannot be mod'd | ||||||
1007 | n_op == Op_Opaque2) { | ||||||
1008 | if (!C->major_progress()) { // If chance of no more loop opts... | ||||||
1009 | _igvn._worklist.push(n); // maybe we'll remove them | ||||||
1010 | } | ||||||
1011 | return n; | ||||||
1012 | } | ||||||
1013 | |||||||
1014 | if (n->is_Con()) { | ||||||
1015 | return n; // No cloning for Con nodes | ||||||
1016 | } | ||||||
1017 | |||||||
1018 | Node *n_ctrl = get_ctrl(n); | ||||||
1019 | if (!n_ctrl) { | ||||||
1020 | return n; // Dead node | ||||||
1021 | } | ||||||
1022 | |||||||
1023 | Node* res = try_move_store_before_loop(n, n_ctrl); | ||||||
1024 | if (res != NULL__null) { | ||||||
1025 | return n; | ||||||
1026 | } | ||||||
1027 | |||||||
1028 | // Attempt to remix address expressions for loop invariants | ||||||
1029 | Node *m = remix_address_expressions( n ); | ||||||
1030 | if( m ) return m; | ||||||
1031 | |||||||
1032 | if (n_op == Op_AddI) { | ||||||
1033 | Node *nn = convert_add_to_muladd( n ); | ||||||
1034 | if ( nn ) return nn; | ||||||
1035 | } | ||||||
1036 | |||||||
1037 | if (n->is_ConstraintCast()) { | ||||||
1038 | Node* dom_cast = n->as_ConstraintCast()->dominating_cast(&_igvn, this); | ||||||
1039 | // ConstraintCastNode::dominating_cast() uses node control input to determine domination. | ||||||
1040 | // Node control inputs don't necessarily agree with loop control info (due to | ||||||
1041 | // transformations happened in between), thus additional dominance check is needed | ||||||
1042 | // to keep loop info valid. | ||||||
1043 | if (dom_cast != NULL__null && is_dominator(get_ctrl(dom_cast), get_ctrl(n))) { | ||||||
1044 | _igvn.replace_node(n, dom_cast); | ||||||
1045 | return dom_cast; | ||||||
1046 | } | ||||||
1047 | } | ||||||
1048 | |||||||
1049 | // Determine if the Node has inputs from some local Phi. | ||||||
1050 | // Returns the block to clone thru. | ||||||
1051 | Node *n_blk = has_local_phi_input( n ); | ||||||
1052 | if( !n_blk ) return n; | ||||||
1053 | |||||||
1054 | // Do not clone the trip counter through on a CountedLoop | ||||||
1055 | // (messes up the canonical shape). | ||||||
1056 | if (((n_blk->is_CountedLoop() || (n_blk->is_Loop() && n_blk->as_Loop()->is_loop_nest_inner_loop())) && n->Opcode() == Op_AddI) || | ||||||
1057 | (n_blk->is_LongCountedLoop() && n->Opcode() == Op_AddL)) { | ||||||
1058 | return n; | ||||||
1059 | } | ||||||
1060 | |||||||
1061 | // Check for having no control input; not pinned. Allow | ||||||
1062 | // dominating control. | ||||||
1063 | if (n->in(0)) { | ||||||
1064 | Node *dom = idom(n_blk); | ||||||
1065 | if (dom_lca(n->in(0), dom) != n->in(0)) { | ||||||
1066 | return n; | ||||||
1067 | } | ||||||
1068 | } | ||||||
1069 | // Policy: when is it profitable. You must get more wins than | ||||||
1070 | // policy before it is considered profitable. Policy is usually 0, | ||||||
1071 | // so 1 win is considered profitable. Big merges will require big | ||||||
1072 | // cloning, so get a larger policy. | ||||||
1073 | int policy = n_blk->req() >> 2; | ||||||
1074 | |||||||
1075 | // If the loop is a candidate for range check elimination, | ||||||
1076 | // delay splitting through it's phi until a later loop optimization | ||||||
1077 | if (n_blk->is_BaseCountedLoop()) { | ||||||
1078 | IdealLoopTree *lp = get_loop(n_blk); | ||||||
1079 | if (lp && lp->_rce_candidate) { | ||||||
1080 | return n; | ||||||
1081 | } | ||||||
1082 | } | ||||||
1083 | |||||||
1084 | if (must_throttle_split_if()) return n; | ||||||
1085 | |||||||
1086 | // Split 'n' through the merge point if it is profitable | ||||||
1087 | Node *phi = split_thru_phi( n, n_blk, policy ); | ||||||
1088 | if (!phi) return n; | ||||||
1089 | |||||||
1090 | // Found a Phi to split thru! | ||||||
1091 | // Replace 'n' with the new phi | ||||||
1092 | _igvn.replace_node( n, phi ); | ||||||
1093 | // Moved a load around the loop, 'en-registering' something. | ||||||
1094 | if (n_blk->is_Loop() && n->is_Load() && | ||||||
1095 | !phi->in(LoopNode::LoopBackControl)->is_Load()) | ||||||
1096 | C->set_major_progress(); | ||||||
1097 | |||||||
1098 | return phi; | ||||||
1099 | } | ||||||
1100 | |||||||
1101 | static bool merge_point_too_heavy(Compile* C, Node* region) { | ||||||
1102 | // Bail out if the region and its phis have too many users. | ||||||
1103 | int weight = 0; | ||||||
1104 | for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { | ||||||
| |||||||
1105 | weight += region->fast_out(i)->outcnt(); | ||||||
1106 | } | ||||||
1107 | int nodes_left = C->max_node_limit() - C->live_nodes(); | ||||||
1108 | if (weight * 8 > nodes_left) { | ||||||
1109 | if (PrintOpto) { | ||||||
1110 | tty->print_cr("*** Split-if bails out: %d nodes, region weight %d", C->unique(), weight); | ||||||
1111 | } | ||||||
1112 | return true; | ||||||
1113 | } else { | ||||||
1114 | return false; | ||||||
1115 | } | ||||||
1116 | } | ||||||
1117 | |||||||
1118 | static bool merge_point_safe(Node* region) { | ||||||
1119 | // 4799512: Stop split_if_with_blocks from splitting a block with a ConvI2LNode | ||||||
1120 | // having a PhiNode input. This sidesteps the dangerous case where the split | ||||||
1121 | // ConvI2LNode may become TOP if the input Value() does not | ||||||
1122 | // overlap the ConvI2L range, leaving a node which may not dominate its | ||||||
1123 | // uses. | ||||||
1124 | // A better fix for this problem can be found in the BugTraq entry, but | ||||||
1125 | // expediency for Mantis demands this hack. | ||||||
1126 | #ifdef _LP641 | ||||||
1127 | for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { | ||||||
1128 | Node* n = region->fast_out(i); | ||||||
1129 | if (n->is_Phi()) { | ||||||
1130 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | ||||||
1131 | Node* m = n->fast_out(j); | ||||||
1132 | if (m->Opcode() == Op_ConvI2L) | ||||||
1133 | return false; | ||||||
1134 | if (m->is_CastII()) { | ||||||
1135 | return false; | ||||||
1136 | } | ||||||
1137 | } | ||||||
1138 | } | ||||||
1139 | } | ||||||
1140 | #endif | ||||||
1141 | return true; | ||||||
1142 | } | ||||||
1143 | |||||||
1144 | |||||||
1145 | //------------------------------place_outside_loop--------------------------------- | ||||||
1146 | // Place some computation outside of this loop on the path to the use passed as argument | ||||||
1147 | Node* PhaseIdealLoop::place_outside_loop(Node* useblock, IdealLoopTree* loop) const { | ||||||
1148 | Node* head = loop->_head; | ||||||
1149 | assert(!loop->is_member(get_loop(useblock)), "must be outside loop")do { if (!(!loop->is_member(get_loop(useblock)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1149, "assert(" "!loop->is_member(get_loop(useblock))" ") failed" , "must be outside loop"); ::breakpoint(); } } while (0); | ||||||
1150 | if (head->is_Loop() && head->as_Loop()->is_strip_mined()) { | ||||||
1151 | loop = loop->_parent; | ||||||
1152 | assert(loop->_head->is_OuterStripMinedLoop(), "malformed strip mined loop")do { if (!(loop->_head->is_OuterStripMinedLoop())) { (* g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1152, "assert(" "loop->_head->is_OuterStripMinedLoop()" ") failed", "malformed strip mined loop"); ::breakpoint(); } } while (0); | ||||||
1153 | } | ||||||
1154 | |||||||
1155 | // Pick control right outside the loop | ||||||
1156 | for (;;) { | ||||||
1157 | Node* dom = idom(useblock); | ||||||
1158 | if (loop->is_member(get_loop(dom)) || | ||||||
1159 | // NeverBranch nodes are not assigned to the loop when constructed | ||||||
1160 | (dom->Opcode() == Op_NeverBranch && loop->is_member(get_loop(dom->in(0))))) { | ||||||
1161 | break; | ||||||
1162 | } | ||||||
1163 | useblock = dom; | ||||||
1164 | } | ||||||
1165 | assert(find_non_split_ctrl(useblock) == useblock, "should be non split control")do { if (!(find_non_split_ctrl(useblock) == useblock)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1165, "assert(" "find_non_split_ctrl(useblock) == useblock" ") failed", "should be non split control"); ::breakpoint(); } } while (0); | ||||||
1166 | return useblock; | ||||||
1167 | } | ||||||
1168 | |||||||
1169 | |||||||
1170 | bool PhaseIdealLoop::identical_backtoback_ifs(Node *n) { | ||||||
1171 | if (!n->is_If() || n->is_BaseCountedLoopEnd()) { | ||||||
1172 | return false; | ||||||
1173 | } | ||||||
1174 | if (!n->in(0)->is_Region()) { | ||||||
1175 | return false; | ||||||
1176 | } | ||||||
1177 | |||||||
1178 | IfNode* n_if = n->as_If(); | ||||||
1179 | if (n_if->proj_out(0)->outcnt() > 1 || n_if->proj_out(1)->outcnt() > 1) { | ||||||
1180 | // Removing the dominated If node by using the split-if optimization does not work if there are data dependencies. | ||||||
1181 | // Some data dependencies depend on its immediate dominator If node and should not be separated from it (e.g. null | ||||||
1182 | // checks, division by zero checks etc.). Bail out for now until data dependencies are correctly handled when | ||||||
1183 | // optimizing back-to-back ifs. | ||||||
1184 | return false; | ||||||
1185 | } | ||||||
1186 | |||||||
1187 | Node* region = n->in(0); | ||||||
1188 | Node* dom = idom(region); | ||||||
1189 | if (!dom->is_If() || dom->in(1) != n->in(1)) { | ||||||
1190 | return false; | ||||||
1191 | } | ||||||
1192 | IfNode* dom_if = dom->as_If(); | ||||||
1193 | Node* proj_true = dom_if->proj_out(1); | ||||||
1194 | Node* proj_false = dom_if->proj_out(0); | ||||||
1195 | |||||||
1196 | for (uint i = 1; i < region->req(); i++) { | ||||||
1197 | if (is_dominator(proj_true, region->in(i))) { | ||||||
1198 | continue; | ||||||
1199 | } | ||||||
1200 | if (is_dominator(proj_false, region->in(i))) { | ||||||
1201 | continue; | ||||||
1202 | } | ||||||
1203 | return false; | ||||||
1204 | } | ||||||
1205 | |||||||
1206 | return true; | ||||||
1207 | } | ||||||
1208 | |||||||
1209 | |||||||
1210 | bool PhaseIdealLoop::can_split_if(Node* n_ctrl) { | ||||||
1211 | if (must_throttle_split_if()) { | ||||||
1212 | return false; | ||||||
1213 | } | ||||||
1214 | |||||||
1215 | // Do not do 'split-if' if irreducible loops are present. | ||||||
1216 | if (_has_irreducible_loops) { | ||||||
1217 | return false; | ||||||
1218 | } | ||||||
1219 | |||||||
1220 | if (merge_point_too_heavy(C, n_ctrl)) { | ||||||
1221 | return false; | ||||||
1222 | } | ||||||
1223 | |||||||
1224 | // Do not do 'split-if' if some paths are dead. First do dead code | ||||||
1225 | // elimination and then see if its still profitable. | ||||||
1226 | for (uint i = 1; i < n_ctrl->req(); i++) { | ||||||
1227 | if (n_ctrl->in(i) == C->top()) { | ||||||
1228 | return false; | ||||||
1229 | } | ||||||
1230 | } | ||||||
1231 | |||||||
1232 | // If trying to do a 'Split-If' at the loop head, it is only | ||||||
1233 | // profitable if the cmp folds up on BOTH paths. Otherwise we | ||||||
1234 | // risk peeling a loop forever. | ||||||
1235 | |||||||
1236 | // CNC - Disabled for now. Requires careful handling of loop | ||||||
1237 | // body selection for the cloned code. Also, make sure we check | ||||||
1238 | // for any input path not being in the same loop as n_ctrl. For | ||||||
1239 | // irreducible loops we cannot check for 'n_ctrl->is_Loop()' | ||||||
1240 | // because the alternative loop entry points won't be converted | ||||||
1241 | // into LoopNodes. | ||||||
1242 | IdealLoopTree *n_loop = get_loop(n_ctrl); | ||||||
1243 | for (uint j = 1; j < n_ctrl->req(); j++) { | ||||||
1244 | if (get_loop(n_ctrl->in(j)) != n_loop) { | ||||||
1245 | return false; | ||||||
1246 | } | ||||||
1247 | } | ||||||
1248 | |||||||
1249 | // Check for safety of the merge point. | ||||||
1250 | if (!merge_point_safe(n_ctrl)) { | ||||||
1251 | return false; | ||||||
1252 | } | ||||||
1253 | |||||||
1254 | return true; | ||||||
1255 | } | ||||||
1256 | |||||||
1257 | // Detect if the node is the inner strip-mined loop | ||||||
1258 | // Return: NULL if it's not the case, or the exit of outer strip-mined loop | ||||||
1259 | static Node* is_inner_of_stripmined_loop(const Node* out) { | ||||||
1260 | Node* out_le = NULL__null; | ||||||
1261 | |||||||
1262 | if (out->is_CountedLoopEnd()) { | ||||||
1263 | const CountedLoopNode* loop = out->as_CountedLoopEnd()->loopnode(); | ||||||
1264 | |||||||
1265 | if (loop != NULL__null && loop->is_strip_mined()) { | ||||||
1266 | out_le = loop->in(LoopNode::EntryControl)->as_OuterStripMinedLoop()->outer_loop_exit(); | ||||||
1267 | } | ||||||
1268 | } | ||||||
1269 | |||||||
1270 | return out_le; | ||||||
1271 | } | ||||||
1272 | |||||||
1273 | //------------------------------split_if_with_blocks_post---------------------- | ||||||
1274 | // Do the real work in a non-recursive function. CFG hackery wants to be | ||||||
1275 | // in the post-order, so it can dirty the I-DOM info and not use the dirtied | ||||||
1276 | // info. | ||||||
1277 | void PhaseIdealLoop::split_if_with_blocks_post(Node *n) { | ||||||
1278 | |||||||
1279 | // Cloning Cmp through Phi's involves the split-if transform. | ||||||
1280 | // FastLock is not used by an If | ||||||
1281 | if (n->is_Cmp() && !n->is_FastLock()) { | ||||||
1282 | Node *n_ctrl = get_ctrl(n); | ||||||
1283 | // Determine if the Node has inputs from some local Phi. | ||||||
1284 | // Returns the block to clone thru. | ||||||
1285 | Node *n_blk = has_local_phi_input(n); | ||||||
1286 | if (n_blk != n_ctrl) { | ||||||
1287 | return; | ||||||
1288 | } | ||||||
1289 | |||||||
1290 | if (!can_split_if(n_ctrl)) { | ||||||
1291 | return; | ||||||
1292 | } | ||||||
1293 | |||||||
1294 | if (n->outcnt() != 1) { | ||||||
1295 | return; // Multiple bool's from 1 compare? | ||||||
1296 | } | ||||||
1297 | Node *bol = n->unique_out(); | ||||||
1298 | assert(bol->is_Bool(), "expect a bool here")do { if (!(bol->is_Bool())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1298, "assert(" "bol->is_Bool()" ") failed", "expect a bool here" ); ::breakpoint(); } } while (0); | ||||||
1299 | if (bol->outcnt() != 1) { | ||||||
1300 | return;// Multiple branches from 1 compare? | ||||||
1301 | } | ||||||
1302 | Node *iff = bol->unique_out(); | ||||||
1303 | |||||||
1304 | // Check some safety conditions | ||||||
1305 | if (iff->is_If()) { // Classic split-if? | ||||||
1306 | if (iff->in(0) != n_ctrl) { | ||||||
1307 | return; // Compare must be in same blk as if | ||||||
1308 | } | ||||||
1309 | } else if (iff->is_CMove()) { // Trying to split-up a CMOVE | ||||||
1310 | // Can't split CMove with different control edge. | ||||||
1311 | if (iff->in(0) != NULL__null && iff->in(0) != n_ctrl ) { | ||||||
1312 | return; | ||||||
1313 | } | ||||||
1314 | if (get_ctrl(iff->in(2)) == n_ctrl || | ||||||
1315 | get_ctrl(iff->in(3)) == n_ctrl) { | ||||||
1316 | return; // Inputs not yet split-up | ||||||
1317 | } | ||||||
1318 | if (get_loop(n_ctrl) != get_loop(get_ctrl(iff))) { | ||||||
1319 | return; // Loop-invar test gates loop-varying CMOVE | ||||||
1320 | } | ||||||
1321 | } else { | ||||||
1322 | return; // some other kind of node, such as an Allocate | ||||||
1323 | } | ||||||
1324 | |||||||
1325 | // When is split-if profitable? Every 'win' on means some control flow | ||||||
1326 | // goes dead, so it's almost always a win. | ||||||
1327 | int policy = 0; | ||||||
1328 | // Split compare 'n' through the merge point if it is profitable | ||||||
1329 | Node *phi = split_thru_phi( n, n_ctrl, policy); | ||||||
1330 | if (!phi) { | ||||||
1331 | return; | ||||||
1332 | } | ||||||
1333 | |||||||
1334 | // Found a Phi to split thru! | ||||||
1335 | // Replace 'n' with the new phi | ||||||
1336 | _igvn.replace_node(n, phi); | ||||||
1337 | |||||||
1338 | // Now split the bool up thru the phi | ||||||
1339 | Node *bolphi = split_thru_phi(bol, n_ctrl, -1); | ||||||
1340 | guarantee(bolphi != NULL, "null boolean phi node")do { if (!(bolphi != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1340, "guarantee(" "bolphi != NULL" ") failed", "null boolean phi node" ); ::breakpoint(); } } while (0); | ||||||
1341 | |||||||
1342 | _igvn.replace_node(bol, bolphi); | ||||||
1343 | assert(iff->in(1) == bolphi, "")do { if (!(iff->in(1) == bolphi)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1343, "assert(" "iff->in(1) == bolphi" ") failed", ""); :: breakpoint(); } } while (0); | ||||||
1344 | |||||||
1345 | if (bolphi->Value(&_igvn)->singleton()) { | ||||||
1346 | return; | ||||||
1347 | } | ||||||
1348 | |||||||
1349 | // Conditional-move? Must split up now | ||||||
1350 | if (!iff->is_If()) { | ||||||
1351 | Node *cmovphi = split_thru_phi(iff, n_ctrl, -1); | ||||||
1352 | _igvn.replace_node(iff, cmovphi); | ||||||
1353 | return; | ||||||
1354 | } | ||||||
1355 | |||||||
1356 | // Now split the IF | ||||||
1357 | do_split_if(iff); | ||||||
1358 | return; | ||||||
1359 | } | ||||||
1360 | |||||||
1361 | // Two identical ifs back to back can be merged | ||||||
1362 | if (identical_backtoback_ifs(n) && can_split_if(n->in(0))) { | ||||||
1363 | Node *n_ctrl = n->in(0); | ||||||
1364 | PhiNode* bolphi = PhiNode::make_blank(n_ctrl, n->in(1)); | ||||||
1365 | IfNode* dom_if = idom(n_ctrl)->as_If(); | ||||||
1366 | Node* proj_true = dom_if->proj_out(1); | ||||||
1367 | Node* proj_false = dom_if->proj_out(0); | ||||||
1368 | Node* con_true = _igvn.makecon(TypeInt::ONE); | ||||||
1369 | Node* con_false = _igvn.makecon(TypeInt::ZERO); | ||||||
1370 | |||||||
1371 | for (uint i = 1; i < n_ctrl->req(); i++) { | ||||||
1372 | if (is_dominator(proj_true, n_ctrl->in(i))) { | ||||||
1373 | bolphi->init_req(i, con_true); | ||||||
1374 | } else { | ||||||
1375 | assert(is_dominator(proj_false, n_ctrl->in(i)), "bad if")do { if (!(is_dominator(proj_false, n_ctrl->in(i)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1375, "assert(" "is_dominator(proj_false, n_ctrl->in(i))" ") failed", "bad if"); ::breakpoint(); } } while (0); | ||||||
1376 | bolphi->init_req(i, con_false); | ||||||
1377 | } | ||||||
1378 | } | ||||||
1379 | register_new_node(bolphi, n_ctrl); | ||||||
1380 | _igvn.replace_input_of(n, 1, bolphi); | ||||||
1381 | |||||||
1382 | // Now split the IF | ||||||
1383 | do_split_if(n); | ||||||
1384 | return; | ||||||
1385 | } | ||||||
1386 | |||||||
1387 | // Check for an IF ready to split; one that has its | ||||||
1388 | // condition codes input coming from a Phi at the block start. | ||||||
1389 | int n_op = n->Opcode(); | ||||||
1390 | |||||||
1391 | // Check for an IF being dominated by another IF same test | ||||||
1392 | if (n_op == Op_If || | ||||||
1393 | n_op == Op_RangeCheck) { | ||||||
1394 | Node *bol = n->in(1); | ||||||
1395 | uint max = bol->outcnt(); | ||||||
1396 | // Check for same test used more than once? | ||||||
1397 | if (max > 1 && bol->is_Bool()) { | ||||||
1398 | // Search up IDOMs to see if this IF is dominated. | ||||||
1399 | Node *cutoff = get_ctrl(bol); | ||||||
1400 | |||||||
1401 | // Now search up IDOMs till cutoff, looking for a dominating test | ||||||
1402 | Node *prevdom = n; | ||||||
1403 | Node *dom = idom(prevdom); | ||||||
1404 | while (dom != cutoff) { | ||||||
1405 | if (dom->req() > 1 && dom->in(1) == bol && prevdom->in(0) == dom && | ||||||
1406 | safe_for_if_replacement(dom)) { | ||||||
1407 | // It's invalid to move control dependent data nodes in the inner | ||||||
1408 | // strip-mined loop, because: | ||||||
1409 | // 1) break validation of LoopNode::verify_strip_mined() | ||||||
1410 | // 2) move code with side-effect in strip-mined loop | ||||||
1411 | // Move to the exit of outer strip-mined loop in that case. | ||||||
1412 | Node* out_le = is_inner_of_stripmined_loop(dom); | ||||||
1413 | if (out_le != NULL__null) { | ||||||
1414 | prevdom = out_le; | ||||||
1415 | } | ||||||
1416 | // Replace the dominated test with an obvious true or false. | ||||||
1417 | // Place it on the IGVN worklist for later cleanup. | ||||||
1418 | C->set_major_progress(); | ||||||
1419 | dominated_by(prevdom, n, false, true); | ||||||
1420 | #ifndef PRODUCT | ||||||
1421 | if( VerifyLoopOptimizations ) verify(); | ||||||
1422 | #endif | ||||||
1423 | return; | ||||||
1424 | } | ||||||
1425 | prevdom = dom; | ||||||
1426 | dom = idom(prevdom); | ||||||
1427 | } | ||||||
1428 | } | ||||||
1429 | } | ||||||
1430 | |||||||
1431 | try_sink_out_of_loop(n); | ||||||
1432 | |||||||
1433 | try_move_store_after_loop(n); | ||||||
1434 | |||||||
1435 | // Check for Opaque2's who's loop has disappeared - who's input is in the | ||||||
1436 | // same loop nest as their output. Remove 'em, they are no longer useful. | ||||||
1437 | if( n_op == Op_Opaque2 && | ||||||
1438 | n->in(1) != NULL__null && | ||||||
1439 | get_loop(get_ctrl(n)) == get_loop(get_ctrl(n->in(1))) ) { | ||||||
1440 | _igvn.replace_node( n, n->in(1) ); | ||||||
1441 | } | ||||||
1442 | } | ||||||
1443 | |||||||
1444 | bool PhaseIdealLoop::safe_for_if_replacement(const Node* dom) const { | ||||||
1445 | if (!dom->is_CountedLoopEnd()) { | ||||||
1446 | return true; | ||||||
1447 | } | ||||||
1448 | CountedLoopEndNode* le = dom->as_CountedLoopEnd(); | ||||||
1449 | CountedLoopNode* cl = le->loopnode(); | ||||||
1450 | if (cl == NULL__null) { | ||||||
1451 | return true; | ||||||
1452 | } | ||||||
1453 | if (!cl->is_main_loop()) { | ||||||
1454 | return true; | ||||||
1455 | } | ||||||
1456 | if (cl->is_canonical_loop_entry() == NULL__null) { | ||||||
1457 | return true; | ||||||
1458 | } | ||||||
1459 | // Further unrolling is possible so loop exit condition might change | ||||||
1460 | return false; | ||||||
1461 | } | ||||||
1462 | |||||||
1463 | // See if a shared loop-varying computation has no loop-varying uses. | ||||||
1464 | // Happens if something is only used for JVM state in uncommon trap exits, | ||||||
1465 | // like various versions of induction variable+offset. Clone the | ||||||
1466 | // computation per usage to allow it to sink out of the loop. | ||||||
1467 | void PhaseIdealLoop::try_sink_out_of_loop(Node* n) { | ||||||
1468 | bool is_raw_to_oop_cast = n->is_ConstraintCast() && | ||||||
1469 | n->in(1)->bottom_type()->isa_rawptr() && | ||||||
1470 | !n->bottom_type()->isa_rawptr(); | ||||||
1471 | if (has_ctrl(n) && | ||||||
1472 | !n->is_Phi() && | ||||||
1473 | !n->is_Bool() && | ||||||
1474 | !n->is_Proj() && | ||||||
1475 | !n->is_MergeMem() && | ||||||
1476 | !n->is_CMove() && | ||||||
1477 | !is_raw_to_oop_cast && // don't extend live ranges of raw oops | ||||||
1478 | n->Opcode() != Op_Opaque4 && | ||||||
1479 | !n->is_Type()) { | ||||||
1480 | Node *n_ctrl = get_ctrl(n); | ||||||
1481 | IdealLoopTree *n_loop = get_loop(n_ctrl); | ||||||
1482 | |||||||
1483 | if (n->in(0) != NULL__null) { | ||||||
1484 | IdealLoopTree* loop_ctrl = get_loop(n->in(0)); | ||||||
1485 | if (n_loop != loop_ctrl && n_loop->is_member(loop_ctrl)) { | ||||||
1486 | // n has a control input inside a loop but get_ctrl() is member of an outer loop. This could happen, for example, | ||||||
1487 | // for Div nodes inside a loop (control input inside loop) without a use except for an UCT (outside the loop). | ||||||
1488 | // Rewire control of n to right outside of the loop, regardless if its input(s) are later sunk or not. | ||||||
1489 | _igvn.replace_input_of(n, 0, place_outside_loop(n_ctrl, loop_ctrl)); | ||||||
1490 | } | ||||||
1491 | } | ||||||
1492 | if (n_loop != _ltree_root && n->outcnt() > 1) { | ||||||
1493 | // Compute early control: needed for anti-dependence analysis. It's also possible that as a result of | ||||||
1494 | // previous transformations in this loop opts round, the node can be hoisted now: early control will tell us. | ||||||
1495 | Node* early_ctrl = compute_early_ctrl(n, n_ctrl); | ||||||
1496 | if (n_loop->is_member(get_loop(early_ctrl)) && // check that this one can't be hoisted now | ||||||
1497 | ctrl_of_all_uses_out_of_loop(n, early_ctrl, n_loop)) { // All uses in outer loops! | ||||||
1498 | assert(!n->is_Store() && !n->is_LoadStore(), "no node with a side effect")do { if (!(!n->is_Store() && !n->is_LoadStore() )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1498, "assert(" "!n->is_Store() && !n->is_LoadStore()" ") failed", "no node with a side effect"); ::breakpoint(); } } while (0); | ||||||
1499 | Node* outer_loop_clone = NULL__null; | ||||||
1500 | for (DUIterator_Last jmin, j = n->last_outs(jmin); j >= jmin;) { | ||||||
1501 | Node* u = n->last_out(j); // Clone private computation per use | ||||||
1502 | _igvn.rehash_node_delayed(u); | ||||||
1503 | Node* x = n->clone(); // Clone computation | ||||||
1504 | Node* x_ctrl = NULL__null; | ||||||
1505 | if (u->is_Phi()) { | ||||||
1506 | // Replace all uses of normal nodes. Replace Phi uses | ||||||
1507 | // individually, so the separate Nodes can sink down | ||||||
1508 | // different paths. | ||||||
1509 | uint k = 1; | ||||||
1510 | while (u->in(k) != n) k++; | ||||||
1511 | u->set_req(k, x); | ||||||
1512 | // x goes next to Phi input path | ||||||
1513 | x_ctrl = u->in(0)->in(k); | ||||||
1514 | // Find control for 'x' next to use but not inside inner loops. | ||||||
1515 | x_ctrl = place_outside_loop(x_ctrl, n_loop); | ||||||
1516 | --j; | ||||||
1517 | } else { // Normal use | ||||||
1518 | if (has_ctrl(u)) { | ||||||
1519 | x_ctrl = get_ctrl(u); | ||||||
1520 | } else { | ||||||
1521 | x_ctrl = u->in(0); | ||||||
1522 | } | ||||||
1523 | // Find control for 'x' next to use but not inside inner loops. | ||||||
1524 | x_ctrl = place_outside_loop(x_ctrl, n_loop); | ||||||
1525 | // Replace all uses | ||||||
1526 | if (u->is_ConstraintCast() && u->bottom_type()->higher_equal(_igvn.type(n)) && u->in(0) == x_ctrl) { | ||||||
1527 | // If we're sinking a chain of data nodes, we might have inserted a cast to pin the use which is not necessary | ||||||
1528 | // anymore now that we're going to pin n as well | ||||||
1529 | _igvn.replace_node(u, x); | ||||||
1530 | --j; | ||||||
1531 | } else { | ||||||
1532 | int nb = u->replace_edge(n, x, &_igvn); | ||||||
1533 | j -= nb; | ||||||
1534 | } | ||||||
1535 | } | ||||||
1536 | |||||||
1537 | if (n->is_Load()) { | ||||||
1538 | // For loads, add a control edge to a CFG node outside of the loop | ||||||
1539 | // to force them to not combine and return back inside the loop | ||||||
1540 | // during GVN optimization (4641526). | ||||||
1541 | assert(x_ctrl == get_late_ctrl_with_anti_dep(x->as_Load(), early_ctrl, x_ctrl), "anti-dependences were already checked")do { if (!(x_ctrl == get_late_ctrl_with_anti_dep(x->as_Load (), early_ctrl, x_ctrl))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1541, "assert(" "x_ctrl == get_late_ctrl_with_anti_dep(x->as_Load(), early_ctrl, x_ctrl)" ") failed", "anti-dependences were already checked"); ::breakpoint (); } } while (0); | ||||||
1542 | |||||||
1543 | IdealLoopTree* x_loop = get_loop(x_ctrl); | ||||||
1544 | Node* x_head = x_loop->_head; | ||||||
1545 | if (x_head->is_Loop() && x_head->is_OuterStripMinedLoop()) { | ||||||
1546 | // Do not add duplicate LoadNodes to the outer strip mined loop | ||||||
1547 | if (outer_loop_clone != NULL__null) { | ||||||
1548 | _igvn.replace_node(x, outer_loop_clone); | ||||||
1549 | continue; | ||||||
1550 | } | ||||||
1551 | outer_loop_clone = x; | ||||||
1552 | } | ||||||
1553 | x->set_req(0, x_ctrl); | ||||||
1554 | } else if (n->in(0) != NULL__null){ | ||||||
1555 | x->set_req(0, x_ctrl); | ||||||
1556 | } | ||||||
1557 | assert(dom_depth(n_ctrl) <= dom_depth(x_ctrl), "n is later than its clone")do { if (!(dom_depth(n_ctrl) <= dom_depth(x_ctrl))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1557, "assert(" "dom_depth(n_ctrl) <= dom_depth(x_ctrl)" ") failed", "n is later than its clone"); ::breakpoint(); } } while (0); | ||||||
1558 | assert(!n_loop->is_member(get_loop(x_ctrl)), "should have moved out of loop")do { if (!(!n_loop->is_member(get_loop(x_ctrl)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1558, "assert(" "!n_loop->is_member(get_loop(x_ctrl))" ") failed" , "should have moved out of loop"); ::breakpoint(); } } while (0); | ||||||
1559 | register_new_node(x, x_ctrl); | ||||||
1560 | |||||||
1561 | // Chain of AddP: (AddP base (AddP base )) must keep the same base after sinking so: | ||||||
1562 | // 1- We don't add a CastPP here when the first one is sunk so if the second one is not, their bases remain | ||||||
1563 | // the same. | ||||||
1564 | // (see 2- below) | ||||||
1565 | assert(!x->is_AddP() || !x->in(AddPNode::Address)->is_AddP() ||do { if (!(!x->is_AddP() || !x->in(AddPNode::Address)-> is_AddP() || x->in(AddPNode::Address)->in(AddPNode::Base ) == x->in(AddPNode::Base) || !x->in(AddPNode::Address) ->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base )))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1567, "assert(" "!x->is_AddP() || !x->in(AddPNode::Address)->is_AddP() || x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base) || !x->in(AddPNode::Address)->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base))" ") failed", "unexpected AddP shape"); ::breakpoint(); } } while (0) | ||||||
1566 | x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base) ||do { if (!(!x->is_AddP() || !x->in(AddPNode::Address)-> is_AddP() || x->in(AddPNode::Address)->in(AddPNode::Base ) == x->in(AddPNode::Base) || !x->in(AddPNode::Address) ->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base )))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1567, "assert(" "!x->is_AddP() || !x->in(AddPNode::Address)->is_AddP() || x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base) || !x->in(AddPNode::Address)->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base))" ") failed", "unexpected AddP shape"); ::breakpoint(); } } while (0) | ||||||
1567 | !x->in(AddPNode::Address)->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base)), "unexpected AddP shape")do { if (!(!x->is_AddP() || !x->in(AddPNode::Address)-> is_AddP() || x->in(AddPNode::Address)->in(AddPNode::Base ) == x->in(AddPNode::Base) || !x->in(AddPNode::Address) ->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base )))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1567, "assert(" "!x->is_AddP() || !x->in(AddPNode::Address)->is_AddP() || x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base) || !x->in(AddPNode::Address)->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base))" ") failed", "unexpected AddP shape"); ::breakpoint(); } } while (0); | ||||||
1568 | if (x->in(0) == NULL__null && !x->is_DecodeNarrowPtr() && | ||||||
1569 | !(x->is_AddP() && x->in(AddPNode::Address)->is_AddP() && x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base))) { | ||||||
1570 | assert(!x->is_Load(), "load should be pinned")do { if (!(!x->is_Load())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1570, "assert(" "!x->is_Load()" ") failed", "load should be pinned" ); ::breakpoint(); } } while (0); | ||||||
1571 | // Use a cast node to pin clone out of loop | ||||||
1572 | Node* cast = NULL__null; | ||||||
1573 | for (uint k = 0; k < x->req(); k++) { | ||||||
1574 | Node* in = x->in(k); | ||||||
1575 | if (in != NULL__null && n_loop->is_member(get_loop(get_ctrl(in)))) { | ||||||
1576 | const Type* in_t = _igvn.type(in); | ||||||
1577 | cast = ConstraintCastNode::make_cast_for_type(x_ctrl, in, in_t, ConstraintCastNode::UnconditionalDependency); | ||||||
1578 | } | ||||||
1579 | if (cast != NULL__null) { | ||||||
1580 | register_new_node(cast, x_ctrl); | ||||||
1581 | x->replace_edge(in, cast); | ||||||
1582 | // Chain of AddP: | ||||||
1583 | // 2- A CastPP of the base is only added now that both AddP nodes are sunk | ||||||
1584 | if (x->is_AddP() && k == AddPNode::Base) { | ||||||
1585 | for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) { | ||||||
1586 | Node* u = x->fast_out(i); | ||||||
1587 | if (u->is_AddP() && u->in(AddPNode::Base) == n->in(AddPNode::Base)) { | ||||||
1588 | _igvn.replace_input_of(u, AddPNode::Base, cast); | ||||||
1589 | assert(u->find_out_with(Op_AddP) == NULL, "more than 2 chained AddP nodes?")do { if (!(u->find_out_with(Op_AddP) == __null)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1589, "assert(" "u->find_out_with(Op_AddP) == __null" ") failed" , "more than 2 chained AddP nodes?"); ::breakpoint(); } } while (0); | ||||||
1590 | } | ||||||
1591 | } | ||||||
1592 | } | ||||||
1593 | break; | ||||||
1594 | } | ||||||
1595 | } | ||||||
1596 | assert(cast != NULL, "must have added a cast to pin the node")do { if (!(cast != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1596, "assert(" "cast != __null" ") failed", "must have added a cast to pin the node" ); ::breakpoint(); } } while (0); | ||||||
1597 | } | ||||||
1598 | } | ||||||
1599 | _igvn.remove_dead_node(n); | ||||||
1600 | } | ||||||
1601 | _dom_lca_tags_round = 0; | ||||||
1602 | } | ||||||
1603 | } | ||||||
1604 | } | ||||||
1605 | |||||||
1606 | Node* PhaseIdealLoop::compute_early_ctrl(Node* n, Node* n_ctrl) { | ||||||
1607 | Node* early_ctrl = NULL__null; | ||||||
1608 | ResourceMark rm; | ||||||
1609 | Unique_Node_List wq; | ||||||
1610 | wq.push(n); | ||||||
1611 | for (uint i = 0; i < wq.size(); i++) { | ||||||
1612 | Node* m = wq.at(i); | ||||||
1613 | Node* c = NULL__null; | ||||||
1614 | if (m->is_CFG()) { | ||||||
1615 | c = m; | ||||||
1616 | } else if (m->pinned()) { | ||||||
1617 | c = m->in(0); | ||||||
1618 | } else { | ||||||
1619 | for (uint j = 0; j < m->req(); j++) { | ||||||
1620 | Node* in = m->in(j); | ||||||
1621 | if (in == NULL__null) { | ||||||
1622 | continue; | ||||||
1623 | } | ||||||
1624 | wq.push(in); | ||||||
1625 | } | ||||||
1626 | } | ||||||
1627 | if (c != NULL__null) { | ||||||
1628 | assert(is_dominator(c, n_ctrl), "")do { if (!(is_dominator(c, n_ctrl))) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1628, "assert(" "is_dominator(c, n_ctrl)" ") failed", ""); :: breakpoint(); } } while (0); | ||||||
1629 | if (early_ctrl == NULL__null) { | ||||||
1630 | early_ctrl = c; | ||||||
1631 | } else if (is_dominator(early_ctrl, c)) { | ||||||
1632 | early_ctrl = c; | ||||||
1633 | } | ||||||
1634 | } | ||||||
1635 | } | ||||||
1636 | assert(is_dominator(early_ctrl, n_ctrl), "early control must dominate current control")do { if (!(is_dominator(early_ctrl, n_ctrl))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1636, "assert(" "is_dominator(early_ctrl, n_ctrl)" ") failed" , "early control must dominate current control"); ::breakpoint (); } } while (0); | ||||||
1637 | return early_ctrl; | ||||||
1638 | } | ||||||
1639 | |||||||
1640 | bool PhaseIdealLoop::ctrl_of_all_uses_out_of_loop(const Node* n, Node* n_ctrl, IdealLoopTree* n_loop) { | ||||||
1641 | for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { | ||||||
1642 | Node* u = n->fast_out(i); | ||||||
1643 | if (u->Opcode() == Op_Opaque1) { | ||||||
1644 | return false; // Found loop limit, bugfix for 4677003 | ||||||
1645 | } | ||||||
1646 | // We can't reuse tags in PhaseIdealLoop::dom_lca_for_get_late_ctrl_internal() so make sure calls to | ||||||
1647 | // get_late_ctrl_with_anti_dep() use their own tag | ||||||
1648 | _dom_lca_tags_round++; | ||||||
1649 | assert(_dom_lca_tags_round != 0, "shouldn't wrap around")do { if (!(_dom_lca_tags_round != 0)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1649, "assert(" "_dom_lca_tags_round != 0" ") failed", "shouldn't wrap around" ); ::breakpoint(); } } while (0); | ||||||
1650 | |||||||
1651 | if (u->is_Phi()) { | ||||||
1652 | for (uint j = 1; j < u->req(); ++j) { | ||||||
1653 | if (u->in(j) == n && !ctrl_of_use_out_of_loop(n, n_ctrl, n_loop, u->in(0)->in(j))) { | ||||||
1654 | return false; | ||||||
1655 | } | ||||||
1656 | } | ||||||
1657 | } else { | ||||||
1658 | Node* ctrl = has_ctrl(u) ? get_ctrl(u) : u->in(0); | ||||||
1659 | if (!ctrl_of_use_out_of_loop(n, n_ctrl, n_loop, ctrl)) { | ||||||
1660 | return false; | ||||||
1661 | } | ||||||
1662 | } | ||||||
1663 | } | ||||||
1664 | return true; | ||||||
1665 | } | ||||||
1666 | |||||||
1667 | bool PhaseIdealLoop::ctrl_of_use_out_of_loop(const Node* n, Node* n_ctrl, IdealLoopTree* n_loop, Node* ctrl) { | ||||||
1668 | if (n->is_Load()) { | ||||||
1669 | ctrl = get_late_ctrl_with_anti_dep(n->as_Load(), n_ctrl, ctrl); | ||||||
1670 | } | ||||||
1671 | IdealLoopTree *u_loop = get_loop(ctrl); | ||||||
1672 | if (u_loop == n_loop) { | ||||||
1673 | return false; // Found loop-varying use | ||||||
1674 | } | ||||||
1675 | if (n_loop->is_member(u_loop)) { | ||||||
1676 | return false; // Found use in inner loop | ||||||
1677 | } | ||||||
1678 | return true; | ||||||
1679 | } | ||||||
1680 | |||||||
1681 | //------------------------------split_if_with_blocks--------------------------- | ||||||
1682 | // Check for aggressive application of 'split-if' optimization, | ||||||
1683 | // using basic block level info. | ||||||
1684 | void PhaseIdealLoop::split_if_with_blocks(VectorSet &visited, Node_Stack &nstack) { | ||||||
1685 | Node* root = C->root(); | ||||||
1686 | visited.set(root->_idx); // first, mark root as visited | ||||||
1687 | // Do pre-visit work for root | ||||||
1688 | Node* n = split_if_with_blocks_pre(root); | ||||||
1689 | uint cnt = n->outcnt(); | ||||||
1690 | uint i = 0; | ||||||
1691 | |||||||
1692 | while (true) { | ||||||
| |||||||
1693 | // Visit all children | ||||||
1694 | if (i < cnt) { | ||||||
1695 | Node* use = n->raw_out(i); | ||||||
1696 | ++i; | ||||||
1697 | if (use->outcnt() != 0 && !visited.test_set(use->_idx)) { | ||||||
1698 | // Now do pre-visit work for this use | ||||||
1699 | use = split_if_with_blocks_pre(use); | ||||||
1700 | nstack.push(n, i); // Save parent and next use's index. | ||||||
1701 | n = use; // Process all children of current use. | ||||||
1702 | cnt = use->outcnt(); | ||||||
1703 | i = 0; | ||||||
1704 | } | ||||||
1705 | } | ||||||
1706 | else { | ||||||
1707 | // All of n's children have been processed, complete post-processing. | ||||||
1708 | if (cnt
| ||||||
1709 | assert(has_node(n), "no dead nodes")do { if (!(has_node(n))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1709, "assert(" "has_node(n)" ") failed", "no dead nodes"); ::breakpoint(); } } while (0); | ||||||
1710 | split_if_with_blocks_post(n); | ||||||
1711 | } | ||||||
1712 | if (must_throttle_split_if()) { | ||||||
1713 | nstack.clear(); | ||||||
1714 | } | ||||||
1715 | if (nstack.is_empty()) { | ||||||
1716 | // Finished all nodes on stack. | ||||||
1717 | break; | ||||||
1718 | } | ||||||
1719 | // Get saved parent node and next use's index. Visit the rest of uses. | ||||||
1720 | n = nstack.node(); | ||||||
1721 | cnt = n->outcnt(); | ||||||
1722 | i = nstack.index(); | ||||||
1723 | nstack.pop(); | ||||||
1724 | } | ||||||
1725 | } | ||||||
1726 | } | ||||||
1727 | |||||||
1728 | |||||||
1729 | //============================================================================= | ||||||
1730 | // | ||||||
1731 | // C L O N E A L O O P B O D Y | ||||||
1732 | // | ||||||
1733 | |||||||
1734 | //------------------------------clone_iff-------------------------------------- | ||||||
1735 | // Passed in a Phi merging (recursively) some nearly equivalent Bool/Cmps. | ||||||
1736 | // "Nearly" because all Nodes have been cloned from the original in the loop, | ||||||
1737 | // but the fall-in edges to the Cmp are different. Clone bool/Cmp pairs | ||||||
1738 | // through the Phi recursively, and return a Bool. | ||||||
1739 | Node* PhaseIdealLoop::clone_iff(PhiNode *phi, IdealLoopTree *loop) { | ||||||
1740 | |||||||
1741 | // Convert this Phi into a Phi merging Bools | ||||||
1742 | uint i; | ||||||
1743 | for (i = 1; i < phi->req(); i++) { | ||||||
1744 | Node *b = phi->in(i); | ||||||
1745 | if (b->is_Phi()) { | ||||||
1746 | _igvn.replace_input_of(phi, i, clone_iff(b->as_Phi(), loop)); | ||||||
1747 | } else { | ||||||
1748 | assert(b->is_Bool() || b->Opcode() == Op_Opaque4, "")do { if (!(b->is_Bool() || b->Opcode() == Op_Opaque4)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1748, "assert(" "b->is_Bool() || b->Opcode() == Op_Opaque4" ") failed", ""); ::breakpoint(); } } while (0); | ||||||
1749 | } | ||||||
1750 | } | ||||||
1751 | |||||||
1752 | Node* n = phi->in(1); | ||||||
1753 | Node* sample_opaque = NULL__null; | ||||||
1754 | Node *sample_bool = NULL__null; | ||||||
1755 | if (n->Opcode() == Op_Opaque4) { | ||||||
1756 | sample_opaque = n; | ||||||
1757 | sample_bool = n->in(1); | ||||||
1758 | assert(sample_bool->is_Bool(), "wrong type")do { if (!(sample_bool->is_Bool())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1758, "assert(" "sample_bool->is_Bool()" ") failed", "wrong type" ); ::breakpoint(); } } while (0); | ||||||
1759 | } else { | ||||||
1760 | sample_bool = n; | ||||||
1761 | } | ||||||
1762 | Node *sample_cmp = sample_bool->in(1); | ||||||
1763 | |||||||
1764 | // Make Phis to merge the Cmp's inputs. | ||||||
1765 | PhiNode *phi1 = new PhiNode(phi->in(0), Type::TOP); | ||||||
1766 | PhiNode *phi2 = new PhiNode(phi->in(0), Type::TOP); | ||||||
1767 | for (i = 1; i < phi->req(); i++) { | ||||||
1768 | Node *n1 = sample_opaque == NULL__null ? phi->in(i)->in(1)->in(1) : phi->in(i)->in(1)->in(1)->in(1); | ||||||
1769 | Node *n2 = sample_opaque == NULL__null ? phi->in(i)->in(1)->in(2) : phi->in(i)->in(1)->in(1)->in(2); | ||||||
1770 | phi1->set_req(i, n1); | ||||||
1771 | phi2->set_req(i, n2); | ||||||
1772 | phi1->set_type(phi1->type()->meet_speculative(n1->bottom_type())); | ||||||
1773 | phi2->set_type(phi2->type()->meet_speculative(n2->bottom_type())); | ||||||
1774 | } | ||||||
1775 | // See if these Phis have been made before. | ||||||
1776 | // Register with optimizer | ||||||
1777 | Node *hit1 = _igvn.hash_find_insert(phi1); | ||||||
1778 | if (hit1) { // Hit, toss just made Phi | ||||||
1779 | _igvn.remove_dead_node(phi1); // Remove new phi | ||||||
1780 | assert(hit1->is_Phi(), "" )do { if (!(hit1->is_Phi())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1780, "assert(" "hit1->is_Phi()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
1781 | phi1 = (PhiNode*)hit1; // Use existing phi | ||||||
1782 | } else { // Miss | ||||||
1783 | _igvn.register_new_node_with_optimizer(phi1); | ||||||
1784 | } | ||||||
1785 | Node *hit2 = _igvn.hash_find_insert(phi2); | ||||||
1786 | if (hit2) { // Hit, toss just made Phi | ||||||
1787 | _igvn.remove_dead_node(phi2); // Remove new phi | ||||||
1788 | assert(hit2->is_Phi(), "" )do { if (!(hit2->is_Phi())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1788, "assert(" "hit2->is_Phi()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
1789 | phi2 = (PhiNode*)hit2; // Use existing phi | ||||||
1790 | } else { // Miss | ||||||
1791 | _igvn.register_new_node_with_optimizer(phi2); | ||||||
1792 | } | ||||||
1793 | // Register Phis with loop/block info | ||||||
1794 | set_ctrl(phi1, phi->in(0)); | ||||||
1795 | set_ctrl(phi2, phi->in(0)); | ||||||
1796 | // Make a new Cmp | ||||||
1797 | Node *cmp = sample_cmp->clone(); | ||||||
1798 | cmp->set_req(1, phi1); | ||||||
1799 | cmp->set_req(2, phi2); | ||||||
1800 | _igvn.register_new_node_with_optimizer(cmp); | ||||||
1801 | set_ctrl(cmp, phi->in(0)); | ||||||
1802 | |||||||
1803 | // Make a new Bool | ||||||
1804 | Node *b = sample_bool->clone(); | ||||||
1805 | b->set_req(1,cmp); | ||||||
1806 | _igvn.register_new_node_with_optimizer(b); | ||||||
1807 | set_ctrl(b, phi->in(0)); | ||||||
1808 | |||||||
1809 | if (sample_opaque != NULL__null) { | ||||||
1810 | Node* opaque = sample_opaque->clone(); | ||||||
1811 | opaque->set_req(1, b); | ||||||
1812 | _igvn.register_new_node_with_optimizer(opaque); | ||||||
1813 | set_ctrl(opaque, phi->in(0)); | ||||||
1814 | return opaque; | ||||||
1815 | } | ||||||
1816 | |||||||
1817 | assert(b->is_Bool(), "")do { if (!(b->is_Bool())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1817, "assert(" "b->is_Bool()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
1818 | return b; | ||||||
1819 | } | ||||||
1820 | |||||||
1821 | //------------------------------clone_bool------------------------------------- | ||||||
1822 | // Passed in a Phi merging (recursively) some nearly equivalent Bool/Cmps. | ||||||
1823 | // "Nearly" because all Nodes have been cloned from the original in the loop, | ||||||
1824 | // but the fall-in edges to the Cmp are different. Clone bool/Cmp pairs | ||||||
1825 | // through the Phi recursively, and return a Bool. | ||||||
1826 | CmpNode *PhaseIdealLoop::clone_bool( PhiNode *phi, IdealLoopTree *loop ) { | ||||||
1827 | uint i; | ||||||
1828 | // Convert this Phi into a Phi merging Bools | ||||||
1829 | for( i = 1; i < phi->req(); i++ ) { | ||||||
1830 | Node *b = phi->in(i); | ||||||
1831 | if( b->is_Phi() ) { | ||||||
1832 | _igvn.replace_input_of(phi, i, clone_bool( b->as_Phi(), loop )); | ||||||
1833 | } else { | ||||||
1834 | assert( b->is_Cmp() || b->is_top(), "inputs are all Cmp or TOP" )do { if (!(b->is_Cmp() || b->is_top())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1834, "assert(" "b->is_Cmp() || b->is_top()" ") failed" , "inputs are all Cmp or TOP"); ::breakpoint(); } } while (0); | ||||||
1835 | } | ||||||
1836 | } | ||||||
1837 | |||||||
1838 | Node *sample_cmp = phi->in(1); | ||||||
1839 | |||||||
1840 | // Make Phis to merge the Cmp's inputs. | ||||||
1841 | PhiNode *phi1 = new PhiNode( phi->in(0), Type::TOP ); | ||||||
1842 | PhiNode *phi2 = new PhiNode( phi->in(0), Type::TOP ); | ||||||
1843 | for( uint j = 1; j < phi->req(); j++ ) { | ||||||
1844 | Node *cmp_top = phi->in(j); // Inputs are all Cmp or TOP | ||||||
1845 | Node *n1, *n2; | ||||||
1846 | if( cmp_top->is_Cmp() ) { | ||||||
1847 | n1 = cmp_top->in(1); | ||||||
1848 | n2 = cmp_top->in(2); | ||||||
1849 | } else { | ||||||
1850 | n1 = n2 = cmp_top; | ||||||
1851 | } | ||||||
1852 | phi1->set_req( j, n1 ); | ||||||
1853 | phi2->set_req( j, n2 ); | ||||||
1854 | phi1->set_type(phi1->type()->meet_speculative(n1->bottom_type())); | ||||||
1855 | phi2->set_type(phi2->type()->meet_speculative(n2->bottom_type())); | ||||||
1856 | } | ||||||
1857 | |||||||
1858 | // See if these Phis have been made before. | ||||||
1859 | // Register with optimizer | ||||||
1860 | Node *hit1 = _igvn.hash_find_insert(phi1); | ||||||
1861 | if( hit1 ) { // Hit, toss just made Phi | ||||||
1862 | _igvn.remove_dead_node(phi1); // Remove new phi | ||||||
1863 | assert( hit1->is_Phi(), "" )do { if (!(hit1->is_Phi())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1863, "assert(" "hit1->is_Phi()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
1864 | phi1 = (PhiNode*)hit1; // Use existing phi | ||||||
1865 | } else { // Miss | ||||||
1866 | _igvn.register_new_node_with_optimizer(phi1); | ||||||
1867 | } | ||||||
1868 | Node *hit2 = _igvn.hash_find_insert(phi2); | ||||||
1869 | if( hit2 ) { // Hit, toss just made Phi | ||||||
1870 | _igvn.remove_dead_node(phi2); // Remove new phi | ||||||
1871 | assert( hit2->is_Phi(), "" )do { if (!(hit2->is_Phi())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1871, "assert(" "hit2->is_Phi()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
1872 | phi2 = (PhiNode*)hit2; // Use existing phi | ||||||
1873 | } else { // Miss | ||||||
1874 | _igvn.register_new_node_with_optimizer(phi2); | ||||||
1875 | } | ||||||
1876 | // Register Phis with loop/block info | ||||||
1877 | set_ctrl(phi1, phi->in(0)); | ||||||
1878 | set_ctrl(phi2, phi->in(0)); | ||||||
1879 | // Make a new Cmp | ||||||
1880 | Node *cmp = sample_cmp->clone(); | ||||||
1881 | cmp->set_req( 1, phi1 ); | ||||||
1882 | cmp->set_req( 2, phi2 ); | ||||||
1883 | _igvn.register_new_node_with_optimizer(cmp); | ||||||
1884 | set_ctrl(cmp, phi->in(0)); | ||||||
1885 | |||||||
1886 | assert( cmp->is_Cmp(), "" )do { if (!(cmp->is_Cmp())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1886, "assert(" "cmp->is_Cmp()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
1887 | return (CmpNode*)cmp; | ||||||
1888 | } | ||||||
1889 | |||||||
1890 | //------------------------------sink_use--------------------------------------- | ||||||
1891 | // If 'use' was in the loop-exit block, it now needs to be sunk | ||||||
1892 | // below the post-loop merge point. | ||||||
1893 | void PhaseIdealLoop::sink_use( Node *use, Node *post_loop ) { | ||||||
1894 | if (!use->is_CFG() && get_ctrl(use) == post_loop->in(2)) { | ||||||
1895 | set_ctrl(use, post_loop); | ||||||
1896 | for (DUIterator j = use->outs(); use->has_out(j); j++) | ||||||
1897 | sink_use(use->out(j), post_loop); | ||||||
1898 | } | ||||||
1899 | } | ||||||
1900 | |||||||
1901 | void PhaseIdealLoop::clone_loop_handle_data_uses(Node* old, Node_List &old_new, | ||||||
1902 | IdealLoopTree* loop, IdealLoopTree* outer_loop, | ||||||
1903 | Node_List*& split_if_set, Node_List*& split_bool_set, | ||||||
1904 | Node_List*& split_cex_set, Node_List& worklist, | ||||||
1905 | uint new_counter, CloneLoopMode mode) { | ||||||
1906 | Node* nnn = old_new[old->_idx]; | ||||||
1907 | // Copy uses to a worklist, so I can munge the def-use info | ||||||
1908 | // with impunity. | ||||||
1909 | for (DUIterator_Fast jmax, j = old->fast_outs(jmax); j < jmax; j++) | ||||||
1910 | worklist.push(old->fast_out(j)); | ||||||
1911 | |||||||
1912 | while( worklist.size() ) { | ||||||
1913 | Node *use = worklist.pop(); | ||||||
1914 | if (!has_node(use)) continue; // Ignore dead nodes | ||||||
1915 | if (use->in(0) == C->top()) continue; | ||||||
1916 | IdealLoopTree *use_loop = get_loop( has_ctrl(use) ? get_ctrl(use) : use ); | ||||||
1917 | // Check for data-use outside of loop - at least one of OLD or USE | ||||||
1918 | // must not be a CFG node. | ||||||
1919 | #ifdef ASSERT1 | ||||||
1920 | if (loop->_head->as_Loop()->is_strip_mined() && outer_loop->is_member(use_loop) && !loop->is_member(use_loop) && old_new[use->_idx] == NULL__null) { | ||||||
1921 | Node* sfpt = loop->_head->as_CountedLoop()->outer_safepoint(); | ||||||
1922 | assert(mode != IgnoreStripMined, "incorrect cloning mode")do { if (!(mode != IgnoreStripMined)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1922, "assert(" "mode != IgnoreStripMined" ") failed", "incorrect cloning mode" ); ::breakpoint(); } } while (0); | ||||||
1923 | assert((mode == ControlAroundStripMined && use == sfpt) || !use->is_reachable_from_root(), "missed a node")do { if (!((mode == ControlAroundStripMined && use == sfpt) || !use->is_reachable_from_root())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1923, "assert(" "(mode == ControlAroundStripMined && use == sfpt) || !use->is_reachable_from_root()" ") failed", "missed a node"); ::breakpoint(); } } while (0); | ||||||
1924 | } | ||||||
1925 | #endif | ||||||
1926 | if (!loop->is_member(use_loop) && !outer_loop->is_member(use_loop) && (!old->is_CFG() || !use->is_CFG())) { | ||||||
1927 | |||||||
1928 | // If the Data use is an IF, that means we have an IF outside of the | ||||||
1929 | // loop that is switching on a condition that is set inside of the | ||||||
1930 | // loop. Happens if people set a loop-exit flag; then test the flag | ||||||
1931 | // in the loop to break the loop, then test is again outside of the | ||||||
1932 | // loop to determine which way the loop exited. | ||||||
1933 | // Loop predicate If node connects to Bool node through Opaque1 node. | ||||||
1934 | if (use->is_If() || use->is_CMove() || C->is_predicate_opaq(use) || use->Opcode() == Op_Opaque4) { | ||||||
1935 | // Since this code is highly unlikely, we lazily build the worklist | ||||||
1936 | // of such Nodes to go split. | ||||||
1937 | if (!split_if_set) { | ||||||
1938 | split_if_set = new Node_List(); | ||||||
1939 | } | ||||||
1940 | split_if_set->push(use); | ||||||
1941 | } | ||||||
1942 | if (use->is_Bool()) { | ||||||
1943 | if (!split_bool_set) { | ||||||
1944 | split_bool_set = new Node_List(); | ||||||
1945 | } | ||||||
1946 | split_bool_set->push(use); | ||||||
1947 | } | ||||||
1948 | if (use->Opcode() == Op_CreateEx) { | ||||||
1949 | if (!split_cex_set) { | ||||||
1950 | split_cex_set = new Node_List(); | ||||||
1951 | } | ||||||
1952 | split_cex_set->push(use); | ||||||
1953 | } | ||||||
1954 | |||||||
1955 | |||||||
1956 | // Get "block" use is in | ||||||
1957 | uint idx = 0; | ||||||
1958 | while( use->in(idx) != old ) idx++; | ||||||
1959 | Node *prev = use->is_CFG() ? use : get_ctrl(use); | ||||||
1960 | assert(!loop->is_member(get_loop(prev)) && !outer_loop->is_member(get_loop(prev)), "" )do { if (!(!loop->is_member(get_loop(prev)) && !outer_loop ->is_member(get_loop(prev)))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1960, "assert(" "!loop->is_member(get_loop(prev)) && !outer_loop->is_member(get_loop(prev))" ") failed", ""); ::breakpoint(); } } while (0); | ||||||
1961 | Node *cfg = prev->_idx >= new_counter | ||||||
1962 | ? prev->in(2) | ||||||
1963 | : idom(prev); | ||||||
1964 | if( use->is_Phi() ) // Phi use is in prior block | ||||||
1965 | cfg = prev->in(idx); // NOT in block of Phi itself | ||||||
1966 | if (cfg->is_top()) { // Use is dead? | ||||||
1967 | _igvn.replace_input_of(use, idx, C->top()); | ||||||
1968 | continue; | ||||||
1969 | } | ||||||
1970 | |||||||
1971 | // If use is referenced through control edge... (idx == 0) | ||||||
1972 | if (mode == IgnoreStripMined && idx == 0) { | ||||||
1973 | LoopNode *head = loop->_head->as_Loop(); | ||||||
1974 | if (head->is_strip_mined() && is_dominator(head->outer_loop_exit(), prev)) { | ||||||
1975 | // That node is outside the inner loop, leave it outside the | ||||||
1976 | // outer loop as well to not confuse verification code. | ||||||
1977 | assert(!loop->_parent->is_member(use_loop), "should be out of the outer loop")do { if (!(!loop->_parent->is_member(use_loop))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 1977, "assert(" "!loop->_parent->is_member(use_loop)" ") failed", "should be out of the outer loop"); ::breakpoint (); } } while (0); | ||||||
1978 | _igvn.replace_input_of(use, 0, head->outer_loop_exit()); | ||||||
1979 | continue; | ||||||
1980 | } | ||||||
1981 | } | ||||||
1982 | |||||||
1983 | while(!outer_loop->is_member(get_loop(cfg))) { | ||||||
1984 | prev = cfg; | ||||||
1985 | cfg = cfg->_idx >= new_counter ? cfg->in(2) : idom(cfg); | ||||||
1986 | } | ||||||
1987 | // If the use occurs after merging several exits from the loop, then | ||||||
1988 | // old value must have dominated all those exits. Since the same old | ||||||
1989 | // value was used on all those exits we did not need a Phi at this | ||||||
1990 | // merge point. NOW we do need a Phi here. Each loop exit value | ||||||
1991 | // is now merged with the peeled body exit; each exit gets its own | ||||||
1992 | // private Phi and those Phis need to be merged here. | ||||||
1993 | Node *phi; | ||||||
1994 | if( prev->is_Region() ) { | ||||||
1995 | if( idx == 0 ) { // Updating control edge? | ||||||
1996 | phi = prev; // Just use existing control | ||||||
1997 | } else { // Else need a new Phi | ||||||
1998 | phi = PhiNode::make( prev, old ); | ||||||
1999 | // Now recursively fix up the new uses of old! | ||||||
2000 | for( uint i = 1; i < prev->req(); i++ ) { | ||||||
2001 | worklist.push(phi); // Onto worklist once for each 'old' input | ||||||
2002 | } | ||||||
2003 | } | ||||||
2004 | } else { | ||||||
2005 | // Get new RegionNode merging old and new loop exits | ||||||
2006 | prev = old_new[prev->_idx]; | ||||||
2007 | assert( prev, "just made this in step 7" )do { if (!(prev)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2007, "assert(" "prev" ") failed", "just made this in step 7" ); ::breakpoint(); } } while (0); | ||||||
2008 | if( idx == 0) { // Updating control edge? | ||||||
2009 | phi = prev; // Just use existing control | ||||||
2010 | } else { // Else need a new Phi | ||||||
2011 | // Make a new Phi merging data values properly | ||||||
2012 | phi = PhiNode::make( prev, old ); | ||||||
2013 | phi->set_req( 1, nnn ); | ||||||
2014 | } | ||||||
2015 | } | ||||||
2016 | // If inserting a new Phi, check for prior hits | ||||||
2017 | if( idx != 0 ) { | ||||||
2018 | Node *hit = _igvn.hash_find_insert(phi); | ||||||
2019 | if( hit == NULL__null ) { | ||||||
2020 | _igvn.register_new_node_with_optimizer(phi); // Register new phi | ||||||
2021 | } else { // or | ||||||
2022 | // Remove the new phi from the graph and use the hit | ||||||
2023 | _igvn.remove_dead_node(phi); | ||||||
2024 | phi = hit; // Use existing phi | ||||||
2025 | } | ||||||
2026 | set_ctrl(phi, prev); | ||||||
2027 | } | ||||||
2028 | // Make 'use' use the Phi instead of the old loop body exit value | ||||||
2029 | _igvn.replace_input_of(use, idx, phi); | ||||||
2030 | if( use->_idx >= new_counter ) { // If updating new phis | ||||||
2031 | // Not needed for correctness, but prevents a weak assert | ||||||
2032 | // in AddPNode from tripping (when we end up with different | ||||||
2033 | // base & derived Phis that will become the same after | ||||||
2034 | // IGVN does CSE). | ||||||
2035 | Node *hit = _igvn.hash_find_insert(use); | ||||||
2036 | if( hit ) // Go ahead and re-hash for hits. | ||||||
2037 | _igvn.replace_node( use, hit ); | ||||||
2038 | } | ||||||
2039 | |||||||
2040 | // If 'use' was in the loop-exit block, it now needs to be sunk | ||||||
2041 | // below the post-loop merge point. | ||||||
2042 | sink_use( use, prev ); | ||||||
2043 | } | ||||||
2044 | } | ||||||
2045 | } | ||||||
2046 | |||||||
2047 | static void clone_outer_loop_helper(Node* n, const IdealLoopTree *loop, const IdealLoopTree* outer_loop, | ||||||
2048 | const Node_List &old_new, Unique_Node_List& wq, PhaseIdealLoop* phase, | ||||||
2049 | bool check_old_new) { | ||||||
2050 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | ||||||
2051 | Node* u = n->fast_out(j); | ||||||
2052 | assert(check_old_new || old_new[u->_idx] == NULL, "shouldn't have been cloned")do { if (!(check_old_new || old_new[u->_idx] == __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2052, "assert(" "check_old_new || old_new[u->_idx] == __null" ") failed", "shouldn't have been cloned"); ::breakpoint(); } } while (0); | ||||||
2053 | if (!u->is_CFG() && (!check_old_new || old_new[u->_idx] == NULL__null)) { | ||||||
2054 | Node* c = phase->get_ctrl(u); | ||||||
2055 | IdealLoopTree* u_loop = phase->get_loop(c); | ||||||
2056 | assert(!loop->is_member(u_loop), "can be in outer loop or out of both loops only")do { if (!(!loop->is_member(u_loop))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2056, "assert(" "!loop->is_member(u_loop)" ") failed", "can be in outer loop or out of both loops only" ); ::breakpoint(); } } while (0); | ||||||
2057 | if (outer_loop->is_member(u_loop) || | ||||||
2058 | // nodes pinned with control in the outer loop but not referenced from the safepoint must be moved out of | ||||||
2059 | // the outer loop too | ||||||
2060 | (u->in(0) != NULL__null && outer_loop->is_member(phase->get_loop(u->in(0))))) { | ||||||
2061 | wq.push(u); | ||||||
2062 | } | ||||||
2063 | } | ||||||
2064 | } | ||||||
2065 | } | ||||||
2066 | |||||||
2067 | void PhaseIdealLoop::clone_outer_loop(LoopNode* head, CloneLoopMode mode, IdealLoopTree *loop, | ||||||
2068 | IdealLoopTree* outer_loop, int dd, Node_List &old_new, | ||||||
2069 | Node_List& extra_data_nodes) { | ||||||
2070 | if (head->is_strip_mined() && mode != IgnoreStripMined) { | ||||||
2071 | CountedLoopNode* cl = head->as_CountedLoop(); | ||||||
2072 | Node* l = cl->outer_loop(); | ||||||
2073 | Node* tail = cl->outer_loop_tail(); | ||||||
2074 | IfNode* le = cl->outer_loop_end(); | ||||||
2075 | Node* sfpt = cl->outer_safepoint(); | ||||||
2076 | CountedLoopEndNode* cle = cl->loopexit(); | ||||||
2077 | CountedLoopNode* new_cl = old_new[cl->_idx]->as_CountedLoop(); | ||||||
2078 | CountedLoopEndNode* new_cle = new_cl->as_CountedLoop()->loopexit_or_null(); | ||||||
2079 | Node* cle_out = cle->proj_out(false); | ||||||
2080 | |||||||
2081 | Node* new_sfpt = NULL__null; | ||||||
2082 | Node* new_cle_out = cle_out->clone(); | ||||||
2083 | old_new.map(cle_out->_idx, new_cle_out); | ||||||
2084 | if (mode == CloneIncludesStripMined) { | ||||||
2085 | // clone outer loop body | ||||||
2086 | Node* new_l = l->clone(); | ||||||
2087 | Node* new_tail = tail->clone(); | ||||||
2088 | IfNode* new_le = le->clone()->as_If(); | ||||||
2089 | new_sfpt = sfpt->clone(); | ||||||
2090 | |||||||
2091 | set_loop(new_l, outer_loop->_parent); | ||||||
2092 | set_idom(new_l, new_l->in(LoopNode::EntryControl), dd); | ||||||
2093 | set_loop(new_cle_out, outer_loop->_parent); | ||||||
2094 | set_idom(new_cle_out, new_cle, dd); | ||||||
2095 | set_loop(new_sfpt, outer_loop->_parent); | ||||||
2096 | set_idom(new_sfpt, new_cle_out, dd); | ||||||
2097 | set_loop(new_le, outer_loop->_parent); | ||||||
2098 | set_idom(new_le, new_sfpt, dd); | ||||||
2099 | set_loop(new_tail, outer_loop->_parent); | ||||||
2100 | set_idom(new_tail, new_le, dd); | ||||||
2101 | set_idom(new_cl, new_l, dd); | ||||||
2102 | |||||||
2103 | old_new.map(l->_idx, new_l); | ||||||
2104 | old_new.map(tail->_idx, new_tail); | ||||||
2105 | old_new.map(le->_idx, new_le); | ||||||
2106 | old_new.map(sfpt->_idx, new_sfpt); | ||||||
2107 | |||||||
2108 | new_l->set_req(LoopNode::LoopBackControl, new_tail); | ||||||
2109 | new_l->set_req(0, new_l); | ||||||
2110 | new_tail->set_req(0, new_le); | ||||||
2111 | new_le->set_req(0, new_sfpt); | ||||||
2112 | new_sfpt->set_req(0, new_cle_out); | ||||||
2113 | new_cle_out->set_req(0, new_cle); | ||||||
2114 | new_cl->set_req(LoopNode::EntryControl, new_l); | ||||||
2115 | |||||||
2116 | _igvn.register_new_node_with_optimizer(new_l); | ||||||
2117 | _igvn.register_new_node_with_optimizer(new_tail); | ||||||
2118 | _igvn.register_new_node_with_optimizer(new_le); | ||||||
2119 | } else { | ||||||
2120 | Node *newhead = old_new[loop->_head->_idx]; | ||||||
2121 | newhead->as_Loop()->clear_strip_mined(); | ||||||
2122 | _igvn.replace_input_of(newhead, LoopNode::EntryControl, newhead->in(LoopNode::EntryControl)->in(LoopNode::EntryControl)); | ||||||
2123 | set_idom(newhead, newhead->in(LoopNode::EntryControl), dd); | ||||||
2124 | } | ||||||
2125 | // Look at data node that were assigned a control in the outer | ||||||
2126 | // loop: they are kept in the outer loop by the safepoint so start | ||||||
2127 | // from the safepoint node's inputs. | ||||||
2128 | IdealLoopTree* outer_loop = get_loop(l); | ||||||
2129 | Node_Stack stack(2); | ||||||
2130 | stack.push(sfpt, 1); | ||||||
2131 | uint new_counter = C->unique(); | ||||||
2132 | while (stack.size() > 0) { | ||||||
2133 | Node* n = stack.node(); | ||||||
2134 | uint i = stack.index(); | ||||||
2135 | while (i < n->req() && | ||||||
2136 | (n->in(i) == NULL__null || | ||||||
2137 | !has_ctrl(n->in(i)) || | ||||||
2138 | get_loop(get_ctrl(n->in(i))) != outer_loop || | ||||||
2139 | (old_new[n->in(i)->_idx] != NULL__null && old_new[n->in(i)->_idx]->_idx >= new_counter))) { | ||||||
2140 | i++; | ||||||
2141 | } | ||||||
2142 | if (i < n->req()) { | ||||||
2143 | stack.set_index(i+1); | ||||||
2144 | stack.push(n->in(i), 0); | ||||||
2145 | } else { | ||||||
2146 | assert(old_new[n->_idx] == NULL || n == sfpt || old_new[n->_idx]->_idx < new_counter, "no clone yet")do { if (!(old_new[n->_idx] == __null || n == sfpt || old_new [n->_idx]->_idx < new_counter)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2146, "assert(" "old_new[n->_idx] == __null || n == sfpt || old_new[n->_idx]->_idx < new_counter" ") failed", "no clone yet"); ::breakpoint(); } } while (0); | ||||||
2147 | Node* m = n == sfpt ? new_sfpt : n->clone(); | ||||||
2148 | if (m != NULL__null) { | ||||||
2149 | for (uint i = 0; i < n->req(); i++) { | ||||||
2150 | if (m->in(i) != NULL__null && old_new[m->in(i)->_idx] != NULL__null) { | ||||||
2151 | m->set_req(i, old_new[m->in(i)->_idx]); | ||||||
2152 | } | ||||||
2153 | } | ||||||
2154 | } else { | ||||||
2155 | assert(n == sfpt && mode != CloneIncludesStripMined, "where's the safepoint clone?")do { if (!(n == sfpt && mode != CloneIncludesStripMined )) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2155, "assert(" "n == sfpt && mode != CloneIncludesStripMined" ") failed", "where's the safepoint clone?"); ::breakpoint(); } } while (0); | ||||||
2156 | } | ||||||
2157 | if (n != sfpt) { | ||||||
2158 | extra_data_nodes.push(n); | ||||||
2159 | _igvn.register_new_node_with_optimizer(m); | ||||||
2160 | assert(get_ctrl(n) == cle_out, "what other control?")do { if (!(get_ctrl(n) == cle_out)) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2160, "assert(" "get_ctrl(n) == cle_out" ") failed", "what other control?" ); ::breakpoint(); } } while (0); | ||||||
2161 | set_ctrl(m, new_cle_out); | ||||||
2162 | old_new.map(n->_idx, m); | ||||||
2163 | } | ||||||
2164 | stack.pop(); | ||||||
2165 | } | ||||||
2166 | } | ||||||
2167 | if (mode == CloneIncludesStripMined) { | ||||||
2168 | _igvn.register_new_node_with_optimizer(new_sfpt); | ||||||
2169 | _igvn.register_new_node_with_optimizer(new_cle_out); | ||||||
2170 | } | ||||||
2171 | // Some other transformation may have pessimistically assign some | ||||||
2172 | // data nodes to the outer loop. Set their control so they are out | ||||||
2173 | // of the outer loop. | ||||||
2174 | ResourceMark rm; | ||||||
2175 | Unique_Node_List wq; | ||||||
2176 | for (uint i = 0; i < extra_data_nodes.size(); i++) { | ||||||
2177 | Node* old = extra_data_nodes.at(i); | ||||||
2178 | clone_outer_loop_helper(old, loop, outer_loop, old_new, wq, this, true); | ||||||
2179 | } | ||||||
2180 | |||||||
2181 | Node* inner_out = sfpt->in(0); | ||||||
2182 | if (inner_out->outcnt() > 1) { | ||||||
2183 | clone_outer_loop_helper(inner_out, loop, outer_loop, old_new, wq, this, true); | ||||||
2184 | } | ||||||
2185 | |||||||
2186 | Node* new_ctrl = cl->outer_loop_exit(); | ||||||
2187 | assert(get_loop(new_ctrl) != outer_loop, "must be out of the loop nest")do { if (!(get_loop(new_ctrl) != outer_loop)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2187, "assert(" "get_loop(new_ctrl) != outer_loop" ") failed" , "must be out of the loop nest"); ::breakpoint(); } } while ( 0); | ||||||
2188 | for (uint i = 0; i < wq.size(); i++) { | ||||||
2189 | Node* n = wq.at(i); | ||||||
2190 | set_ctrl(n, new_ctrl); | ||||||
2191 | if (n->in(0) != NULL__null) { | ||||||
2192 | _igvn.replace_input_of(n, 0, new_ctrl); | ||||||
2193 | } | ||||||
2194 | clone_outer_loop_helper(n, loop, outer_loop, old_new, wq, this, false); | ||||||
2195 | } | ||||||
2196 | } else { | ||||||
2197 | Node *newhead = old_new[loop->_head->_idx]; | ||||||
2198 | set_idom(newhead, newhead->in(LoopNode::EntryControl), dd); | ||||||
2199 | } | ||||||
2200 | } | ||||||
2201 | |||||||
2202 | //------------------------------clone_loop------------------------------------- | ||||||
2203 | // | ||||||
2204 | // C L O N E A L O O P B O D Y | ||||||
2205 | // | ||||||
2206 | // This is the basic building block of the loop optimizations. It clones an | ||||||
2207 | // entire loop body. It makes an old_new loop body mapping; with this mapping | ||||||
2208 | // you can find the new-loop equivalent to an old-loop node. All new-loop | ||||||
2209 | // nodes are exactly equal to their old-loop counterparts, all edges are the | ||||||
2210 | // same. All exits from the old-loop now have a RegionNode that merges the | ||||||
2211 | // equivalent new-loop path. This is true even for the normal "loop-exit" | ||||||
2212 | // condition. All uses of loop-invariant old-loop values now come from (one | ||||||
2213 | // or more) Phis that merge their new-loop equivalents. | ||||||
2214 | // | ||||||
2215 | // This operation leaves the graph in an illegal state: there are two valid | ||||||
2216 | // control edges coming from the loop pre-header to both loop bodies. I'll | ||||||
2217 | // definitely have to hack the graph after running this transform. | ||||||
2218 | // | ||||||
2219 | // From this building block I will further edit edges to perform loop peeling | ||||||
2220 | // or loop unrolling or iteration splitting (Range-Check-Elimination), etc. | ||||||
2221 | // | ||||||
2222 | // Parameter side_by_size_idom: | ||||||
2223 | // When side_by_size_idom is NULL, the dominator tree is constructed for | ||||||
2224 | // the clone loop to dominate the original. Used in construction of | ||||||
2225 | // pre-main-post loop sequence. | ||||||
2226 | // When nonnull, the clone and original are side-by-side, both are | ||||||
2227 | // dominated by the side_by_side_idom node. Used in construction of | ||||||
2228 | // unswitched loops. | ||||||
2229 | void PhaseIdealLoop::clone_loop( IdealLoopTree *loop, Node_List &old_new, int dd, | ||||||
2230 | CloneLoopMode mode, Node* side_by_side_idom) { | ||||||
2231 | |||||||
2232 | LoopNode* head = loop->_head->as_Loop(); | ||||||
2233 | head->verify_strip_mined(1); | ||||||
2234 | |||||||
2235 | if (C->do_vector_loop() && PrintOpto) { | ||||||
2236 | const char* mname = C->method()->name()->as_quoted_ascii(); | ||||||
2237 | if (mname != NULL__null) { | ||||||
2238 | tty->print("PhaseIdealLoop::clone_loop: for vectorize method %s\n", mname); | ||||||
2239 | } | ||||||
2240 | } | ||||||
2241 | |||||||
2242 | CloneMap& cm = C->clone_map(); | ||||||
2243 | Dict* dict = cm.dict(); | ||||||
2244 | if (C->do_vector_loop()) { | ||||||
2245 | cm.set_clone_idx(cm.max_gen()+1); | ||||||
2246 | #ifndef PRODUCT | ||||||
2247 | if (PrintOpto) { | ||||||
2248 | tty->print_cr("PhaseIdealLoop::clone_loop: _clone_idx %d", cm.clone_idx()); | ||||||
2249 | loop->dump_head(); | ||||||
2250 | } | ||||||
2251 | #endif | ||||||
2252 | } | ||||||
2253 | |||||||
2254 | // Step 1: Clone the loop body. Make the old->new mapping. | ||||||
2255 | uint i; | ||||||
2256 | for (i = 0; i < loop->_body.size(); i++) { | ||||||
2257 | Node* old = loop->_body.at(i); | ||||||
2258 | Node* nnn = old->clone(); | ||||||
2259 | old_new.map(old->_idx, nnn); | ||||||
2260 | if (old->is_reduction()) { | ||||||
2261 | // Reduction flag is not copied by default. Copy it here when cloning the entire loop body. | ||||||
2262 | nnn->add_flag(Node::Flag_is_reduction); | ||||||
2263 | } | ||||||
2264 | if (C->do_vector_loop()) { | ||||||
2265 | cm.verify_insert_and_clone(old, nnn, cm.clone_idx()); | ||||||
2266 | } | ||||||
2267 | _igvn.register_new_node_with_optimizer(nnn); | ||||||
2268 | } | ||||||
2269 | |||||||
2270 | IdealLoopTree* outer_loop = (head->is_strip_mined() && mode != IgnoreStripMined) ? get_loop(head->as_CountedLoop()->outer_loop()) : loop; | ||||||
2271 | |||||||
2272 | // Step 2: Fix the edges in the new body. If the old input is outside the | ||||||
2273 | // loop use it. If the old input is INside the loop, use the corresponding | ||||||
2274 | // new node instead. | ||||||
2275 | for( i = 0; i < loop->_body.size(); i++ ) { | ||||||
2276 | Node *old = loop->_body.at(i); | ||||||
2277 | Node *nnn = old_new[old->_idx]; | ||||||
2278 | // Fix CFG/Loop controlling the new node | ||||||
2279 | if (has_ctrl(old)) { | ||||||
2280 | set_ctrl(nnn, old_new[get_ctrl(old)->_idx]); | ||||||
2281 | } else { | ||||||
2282 | set_loop(nnn, outer_loop->_parent); | ||||||
2283 | if (old->outcnt() > 0) { | ||||||
2284 | set_idom( nnn, old_new[idom(old)->_idx], dd ); | ||||||
2285 | } | ||||||
2286 | } | ||||||
2287 | // Correct edges to the new node | ||||||
2288 | for( uint j = 0; j < nnn->req(); j++ ) { | ||||||
2289 | Node *n = nnn->in(j); | ||||||
2290 | if( n ) { | ||||||
2291 | IdealLoopTree *old_in_loop = get_loop( has_ctrl(n) ? get_ctrl(n) : n ); | ||||||
2292 | if( loop->is_member( old_in_loop ) ) | ||||||
2293 | nnn->set_req(j, old_new[n->_idx]); | ||||||
2294 | } | ||||||
2295 | } | ||||||
2296 | _igvn.hash_find_insert(nnn); | ||||||
2297 | } | ||||||
2298 | |||||||
2299 | Node_List extra_data_nodes; // data nodes in the outer strip mined loop | ||||||
2300 | clone_outer_loop(head, mode, loop, outer_loop, dd, old_new, extra_data_nodes); | ||||||
2301 | |||||||
2302 | // Step 3: Now fix control uses. Loop varying control uses have already | ||||||
2303 | // been fixed up (as part of all input edges in Step 2). Loop invariant | ||||||
2304 | // control uses must be either an IfFalse or an IfTrue. Make a merge | ||||||
2305 | // point to merge the old and new IfFalse/IfTrue nodes; make the use | ||||||
2306 | // refer to this. | ||||||
2307 | Node_List worklist; | ||||||
2308 | uint new_counter = C->unique(); | ||||||
2309 | for( i = 0; i < loop->_body.size(); i++ ) { | ||||||
2310 | Node* old = loop->_body.at(i); | ||||||
2311 | if( !old->is_CFG() ) continue; | ||||||
2312 | |||||||
2313 | // Copy uses to a worklist, so I can munge the def-use info | ||||||
2314 | // with impunity. | ||||||
2315 | for (DUIterator_Fast jmax, j = old->fast_outs(jmax); j < jmax; j++) | ||||||
2316 | worklist.push(old->fast_out(j)); | ||||||
2317 | |||||||
2318 | while( worklist.size() ) { // Visit all uses | ||||||
2319 | Node *use = worklist.pop(); | ||||||
2320 | if (!has_node(use)) continue; // Ignore dead nodes | ||||||
2321 | IdealLoopTree *use_loop = get_loop( has_ctrl(use) ? get_ctrl(use) : use ); | ||||||
2322 | if( !loop->is_member( use_loop ) && use->is_CFG() ) { | ||||||
2323 | // Both OLD and USE are CFG nodes here. | ||||||
2324 | assert( use->is_Proj(), "" )do { if (!(use->is_Proj())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2324, "assert(" "use->is_Proj()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
2325 | Node* nnn = old_new[old->_idx]; | ||||||
2326 | |||||||
2327 | Node* newuse = NULL__null; | ||||||
2328 | if (head->is_strip_mined() && mode != IgnoreStripMined) { | ||||||
2329 | CountedLoopNode* cl = head->as_CountedLoop(); | ||||||
2330 | CountedLoopEndNode* cle = cl->loopexit(); | ||||||
2331 | Node* cle_out = cle->proj_out_or_null(false); | ||||||
2332 | if (use == cle_out) { | ||||||
2333 | IfNode* le = cl->outer_loop_end(); | ||||||
2334 | use = le->proj_out(false); | ||||||
2335 | use_loop = get_loop(use); | ||||||
2336 | if (mode == CloneIncludesStripMined) { | ||||||
2337 | nnn = old_new[le->_idx]; | ||||||
2338 | } else { | ||||||
2339 | newuse = old_new[cle_out->_idx]; | ||||||
2340 | } | ||||||
2341 | } | ||||||
2342 | } | ||||||
2343 | if (newuse == NULL__null) { | ||||||
2344 | newuse = use->clone(); | ||||||
2345 | } | ||||||
2346 | |||||||
2347 | // Clone the loop exit control projection | ||||||
2348 | if (C->do_vector_loop()) { | ||||||
2349 | cm.verify_insert_and_clone(use, newuse, cm.clone_idx()); | ||||||
2350 | } | ||||||
2351 | newuse->set_req(0,nnn); | ||||||
2352 | _igvn.register_new_node_with_optimizer(newuse); | ||||||
2353 | set_loop(newuse, use_loop); | ||||||
2354 | set_idom(newuse, nnn, dom_depth(nnn) + 1 ); | ||||||
2355 | |||||||
2356 | // We need a Region to merge the exit from the peeled body and the | ||||||
2357 | // exit from the old loop body. | ||||||
2358 | RegionNode *r = new RegionNode(3); | ||||||
2359 | // Map the old use to the new merge point | ||||||
2360 | old_new.map( use->_idx, r ); | ||||||
2361 | uint dd_r = MIN2(dom_depth(newuse),dom_depth(use)); | ||||||
2362 | assert( dd_r >= dom_depth(dom_lca(newuse,use)), "" )do { if (!(dd_r >= dom_depth(dom_lca(newuse,use)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2362, "assert(" "dd_r >= dom_depth(dom_lca(newuse,use))" ") failed", ""); ::breakpoint(); } } while (0); | ||||||
2363 | |||||||
2364 | // The original user of 'use' uses 'r' instead. | ||||||
2365 | for (DUIterator_Last lmin, l = use->last_outs(lmin); l >= lmin;) { | ||||||
2366 | Node* useuse = use->last_out(l); | ||||||
2367 | _igvn.rehash_node_delayed(useuse); | ||||||
2368 | uint uses_found = 0; | ||||||
2369 | if( useuse->in(0) == use ) { | ||||||
2370 | useuse->set_req(0, r); | ||||||
2371 | uses_found++; | ||||||
2372 | if( useuse->is_CFG() ) { | ||||||
2373 | // This is not a dom_depth > dd_r because when new | ||||||
2374 | // control flow is constructed by a loop opt, a node and | ||||||
2375 | // its dominator can end up at the same dom_depth | ||||||
2376 | assert(dom_depth(useuse) >= dd_r, "")do { if (!(dom_depth(useuse) >= dd_r)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2376, "assert(" "dom_depth(useuse) >= dd_r" ") failed", "" ); ::breakpoint(); } } while (0); | ||||||
2377 | set_idom(useuse, r, dom_depth(useuse)); | ||||||
2378 | } | ||||||
2379 | } | ||||||
2380 | for( uint k = 1; k < useuse->req(); k++ ) { | ||||||
2381 | if( useuse->in(k) == use ) { | ||||||
2382 | useuse->set_req(k, r); | ||||||
2383 | uses_found++; | ||||||
2384 | if (useuse->is_Loop() && k == LoopNode::EntryControl) { | ||||||
2385 | // This is not a dom_depth > dd_r because when new | ||||||
2386 | // control flow is constructed by a loop opt, a node | ||||||
2387 | // and its dominator can end up at the same dom_depth | ||||||
2388 | assert(dom_depth(useuse) >= dd_r , "")do { if (!(dom_depth(useuse) >= dd_r)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2388, "assert(" "dom_depth(useuse) >= dd_r" ") failed", "" ); ::breakpoint(); } } while (0); | ||||||
2389 | set_idom(useuse, r, dom_depth(useuse)); | ||||||
2390 | } | ||||||
2391 | } | ||||||
2392 | } | ||||||
2393 | l -= uses_found; // we deleted 1 or more copies of this edge | ||||||
2394 | } | ||||||
2395 | |||||||
2396 | // Now finish up 'r' | ||||||
2397 | r->set_req( 1, newuse ); | ||||||
2398 | r->set_req( 2, use ); | ||||||
2399 | _igvn.register_new_node_with_optimizer(r); | ||||||
2400 | set_loop(r, use_loop); | ||||||
2401 | set_idom(r, !side_by_side_idom ? newuse->in(0) : side_by_side_idom, dd_r); | ||||||
2402 | } // End of if a loop-exit test | ||||||
2403 | } | ||||||
2404 | } | ||||||
2405 | |||||||
2406 | // Step 4: If loop-invariant use is not control, it must be dominated by a | ||||||
2407 | // loop exit IfFalse/IfTrue. Find "proper" loop exit. Make a Region | ||||||
2408 | // there if needed. Make a Phi there merging old and new used values. | ||||||
2409 | Node_List *split_if_set = NULL__null; | ||||||
2410 | Node_List *split_bool_set = NULL__null; | ||||||
2411 | Node_List *split_cex_set = NULL__null; | ||||||
2412 | for( i = 0; i < loop->_body.size(); i++ ) { | ||||||
2413 | Node* old = loop->_body.at(i); | ||||||
2414 | clone_loop_handle_data_uses(old, old_new, loop, outer_loop, split_if_set, | ||||||
2415 | split_bool_set, split_cex_set, worklist, new_counter, | ||||||
2416 | mode); | ||||||
2417 | } | ||||||
2418 | |||||||
2419 | for (i = 0; i < extra_data_nodes.size(); i++) { | ||||||
2420 | Node* old = extra_data_nodes.at(i); | ||||||
2421 | clone_loop_handle_data_uses(old, old_new, loop, outer_loop, split_if_set, | ||||||
2422 | split_bool_set, split_cex_set, worklist, new_counter, | ||||||
2423 | mode); | ||||||
2424 | } | ||||||
2425 | |||||||
2426 | // Check for IFs that need splitting/cloning. Happens if an IF outside of | ||||||
2427 | // the loop uses a condition set in the loop. The original IF probably | ||||||
2428 | // takes control from one or more OLD Regions (which in turn get from NEW | ||||||
2429 | // Regions). In any case, there will be a set of Phis for each merge point | ||||||
2430 | // from the IF up to where the original BOOL def exists the loop. | ||||||
2431 | if (split_if_set) { | ||||||
2432 | while (split_if_set->size()) { | ||||||
2433 | Node *iff = split_if_set->pop(); | ||||||
2434 | if (iff->in(1)->is_Phi()) { | ||||||
2435 | Node *b = clone_iff(iff->in(1)->as_Phi(), loop); | ||||||
2436 | _igvn.replace_input_of(iff, 1, b); | ||||||
2437 | } | ||||||
2438 | } | ||||||
2439 | } | ||||||
2440 | if (split_bool_set) { | ||||||
2441 | while (split_bool_set->size()) { | ||||||
2442 | Node *b = split_bool_set->pop(); | ||||||
2443 | Node *phi = b->in(1); | ||||||
2444 | assert(phi->is_Phi(), "")do { if (!(phi->is_Phi())) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2444, "assert(" "phi->is_Phi()" ") failed", ""); ::breakpoint (); } } while (0); | ||||||
2445 | CmpNode *cmp = clone_bool((PhiNode*)phi, loop); | ||||||
2446 | _igvn.replace_input_of(b, 1, cmp); | ||||||
2447 | } | ||||||
2448 | } | ||||||
2449 | if (split_cex_set) { | ||||||
2450 | while (split_cex_set->size()) { | ||||||
2451 | Node *b = split_cex_set->pop(); | ||||||
2452 | assert(b->in(0)->is_Region(), "")do { if (!(b->in(0)->is_Region())) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2452, "assert(" "b->in(0)->is_Region()" ") failed", "" ); ::breakpoint(); } } while (0); | ||||||
2453 | assert(b->in(1)->is_Phi(), "")do { if (!(b->in(1)->is_Phi())) { (*g_assert_poison) = 'X' ;; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2453, "assert(" "b->in(1)->is_Phi()" ") failed", ""); ::breakpoint(); } } while (0); | ||||||
2454 | assert(b->in(0)->in(0) == b->in(1)->in(0), "")do { if (!(b->in(0)->in(0) == b->in(1)->in(0))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2454, "assert(" "b->in(0)->in(0) == b->in(1)->in(0)" ") failed", ""); ::breakpoint(); } } while (0); | ||||||
2455 | split_up(b, b->in(0), NULL__null); | ||||||
2456 | } | ||||||
2457 | } | ||||||
2458 | |||||||
2459 | } | ||||||
2460 | |||||||
2461 | |||||||
2462 | //---------------------- stride_of_possible_iv ------------------------------------- | ||||||
2463 | // Looks for an iff/bool/comp with one operand of the compare | ||||||
2464 | // being a cycle involving an add and a phi, | ||||||
2465 | // with an optional truncation (left-shift followed by a right-shift) | ||||||
2466 | // of the add. Returns zero if not an iv. | ||||||
2467 | int PhaseIdealLoop::stride_of_possible_iv(Node* iff) { | ||||||
2468 | Node* trunc1 = NULL__null; | ||||||
2469 | Node* trunc2 = NULL__null; | ||||||
2470 | const TypeInteger* ttype = NULL__null; | ||||||
2471 | if (!iff->is_If() || iff->in(1) == NULL__null || !iff->in(1)->is_Bool()) { | ||||||
2472 | return 0; | ||||||
2473 | } | ||||||
2474 | BoolNode* bl = iff->in(1)->as_Bool(); | ||||||
2475 | Node* cmp = bl->in(1); | ||||||
2476 | if (!cmp || (cmp->Opcode() != Op_CmpI && cmp->Opcode() != Op_CmpU)) { | ||||||
2477 | return 0; | ||||||
2478 | } | ||||||
2479 | // Must have an invariant operand | ||||||
2480 | if (is_member(get_loop(iff), get_ctrl(cmp->in(2)))) { | ||||||
2481 | return 0; | ||||||
2482 | } | ||||||
2483 | Node* add2 = NULL__null; | ||||||
2484 | Node* cmp1 = cmp->in(1); | ||||||
2485 | if (cmp1->is_Phi()) { | ||||||
2486 | // (If (Bool (CmpX phi:(Phi ...(Optional-trunc(AddI phi add2))) ))) | ||||||
2487 | Node* phi = cmp1; | ||||||
2488 | for (uint i = 1; i < phi->req(); i++) { | ||||||
2489 | Node* in = phi->in(i); | ||||||
2490 | Node* add = CountedLoopNode::match_incr_with_optional_truncation(in, | ||||||
2491 | &trunc1, &trunc2, &ttype, T_INT); | ||||||
2492 | if (add && add->in(1) == phi) { | ||||||
2493 | add2 = add->in(2); | ||||||
2494 | break; | ||||||
2495 | } | ||||||
2496 | } | ||||||
2497 | } else { | ||||||
2498 | // (If (Bool (CmpX addtrunc:(Optional-trunc((AddI (Phi ...addtrunc...) add2)) ))) | ||||||
2499 | Node* addtrunc = cmp1; | ||||||
2500 | Node* add = CountedLoopNode::match_incr_with_optional_truncation(addtrunc, | ||||||
2501 | &trunc1, &trunc2, &ttype, T_INT); | ||||||
2502 | if (add && add->in(1)->is_Phi()) { | ||||||
2503 | Node* phi = add->in(1); | ||||||
2504 | for (uint i = 1; i < phi->req(); i++) { | ||||||
2505 | if (phi->in(i) == addtrunc) { | ||||||
2506 | add2 = add->in(2); | ||||||
2507 | break; | ||||||
2508 | } | ||||||
2509 | } | ||||||
2510 | } | ||||||
2511 | } | ||||||
2512 | if (add2 != NULL__null) { | ||||||
2513 | const TypeInt* add2t = _igvn.type(add2)->is_int(); | ||||||
2514 | if (add2t->is_con()) { | ||||||
2515 | return add2t->get_con(); | ||||||
2516 | } | ||||||
2517 | } | ||||||
2518 | return 0; | ||||||
2519 | } | ||||||
2520 | |||||||
2521 | |||||||
2522 | //---------------------- stay_in_loop ------------------------------------- | ||||||
2523 | // Return the (unique) control output node that's in the loop (if it exists.) | ||||||
2524 | Node* PhaseIdealLoop::stay_in_loop( Node* n, IdealLoopTree *loop) { | ||||||
2525 | Node* unique = NULL__null; | ||||||
2526 | if (!n) return NULL__null; | ||||||
2527 | for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { | ||||||
2528 | Node* use = n->fast_out(i); | ||||||
2529 | if (!has_ctrl(use) && loop->is_member(get_loop(use))) { | ||||||
2530 | if (unique != NULL__null) { | ||||||
2531 | return NULL__null; | ||||||
2532 | } | ||||||
2533 | unique = use; | ||||||
2534 | } | ||||||
2535 | } | ||||||
2536 | return unique; | ||||||
2537 | } | ||||||
2538 | |||||||
2539 | //------------------------------ register_node ------------------------------------- | ||||||
2540 | // Utility to register node "n" with PhaseIdealLoop | ||||||
2541 | void PhaseIdealLoop::register_node(Node* n, IdealLoopTree *loop, Node* pred, int ddepth) { | ||||||
2542 | _igvn.register_new_node_with_optimizer(n); | ||||||
2543 | loop->_body.push(n); | ||||||
2544 | if (n->is_CFG()) { | ||||||
2545 | set_loop(n, loop); | ||||||
2546 | set_idom(n, pred, ddepth); | ||||||
2547 | } else { | ||||||
2548 | set_ctrl(n, pred); | ||||||
2549 | } | ||||||
2550 | } | ||||||
2551 | |||||||
2552 | //------------------------------ proj_clone ------------------------------------- | ||||||
2553 | // Utility to create an if-projection | ||||||
2554 | ProjNode* PhaseIdealLoop::proj_clone(ProjNode* p, IfNode* iff) { | ||||||
2555 | ProjNode* c = p->clone()->as_Proj(); | ||||||
2556 | c->set_req(0, iff); | ||||||
2557 | return c; | ||||||
2558 | } | ||||||
2559 | |||||||
2560 | //------------------------------ short_circuit_if ------------------------------------- | ||||||
2561 | // Force the iff control output to be the live_proj | ||||||
2562 | Node* PhaseIdealLoop::short_circuit_if(IfNode* iff, ProjNode* live_proj) { | ||||||
2563 | guarantee(live_proj != NULL, "null projection")do { if (!(live_proj != __null)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2563, "guarantee(" "live_proj != NULL" ") failed", "null projection" ); ::breakpoint(); } } while (0); | ||||||
2564 | int proj_con = live_proj->_con; | ||||||
2565 | assert(proj_con == 0 || proj_con == 1, "false or true projection")do { if (!(proj_con == 0 || proj_con == 1)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2565, "assert(" "proj_con == 0 || proj_con == 1" ") failed" , "false or true projection"); ::breakpoint(); } } while (0); | ||||||
2566 | Node *con = _igvn.intcon(proj_con); | ||||||
2567 | set_ctrl(con, C->root()); | ||||||
2568 | if (iff) { | ||||||
2569 | iff->set_req(1, con); | ||||||
2570 | } | ||||||
2571 | return con; | ||||||
2572 | } | ||||||
2573 | |||||||
2574 | //------------------------------ insert_if_before_proj ------------------------------------- | ||||||
2575 | // Insert a new if before an if projection (* - new node) | ||||||
2576 | // | ||||||
2577 | // before | ||||||
2578 | // if(test) | ||||||
2579 | // / \ | ||||||
2580 | // v v | ||||||
2581 | // other-proj proj (arg) | ||||||
2582 | // | ||||||
2583 | // after | ||||||
2584 | // if(test) | ||||||
2585 | // / \ | ||||||
2586 | // / v | ||||||
2587 | // | * proj-clone | ||||||
2588 | // v | | ||||||
2589 | // other-proj v | ||||||
2590 | // * new_if(relop(cmp[IU](left,right))) | ||||||
2591 | // / \ | ||||||
2592 | // v v | ||||||
2593 | // * new-proj proj | ||||||
2594 | // (returned) | ||||||
2595 | // | ||||||
2596 | ProjNode* PhaseIdealLoop::insert_if_before_proj(Node* left, bool Signed, BoolTest::mask relop, Node* right, ProjNode* proj) { | ||||||
2597 | IfNode* iff = proj->in(0)->as_If(); | ||||||
2598 | IdealLoopTree *loop = get_loop(proj); | ||||||
2599 | ProjNode *other_proj = iff->proj_out(!proj->is_IfTrue())->as_Proj(); | ||||||
2600 | int ddepth = dom_depth(proj); | ||||||
2601 | |||||||
2602 | _igvn.rehash_node_delayed(iff); | ||||||
2603 | _igvn.rehash_node_delayed(proj); | ||||||
2604 | |||||||
2605 | proj->set_req(0, NULL__null); // temporary disconnect | ||||||
2606 | ProjNode* proj2 = proj_clone(proj, iff); | ||||||
2607 | register_node(proj2, loop, iff, ddepth); | ||||||
2608 | |||||||
2609 | Node* cmp = Signed ? (Node*) new CmpINode(left, right) : (Node*) new CmpUNode(left, right); | ||||||
2610 | register_node(cmp, loop, proj2, ddepth); | ||||||
2611 | |||||||
2612 | BoolNode* bol = new BoolNode(cmp, relop); | ||||||
2613 | register_node(bol, loop, proj2, ddepth); | ||||||
2614 | |||||||
2615 | int opcode = iff->Opcode(); | ||||||
2616 | assert(opcode == Op_If || opcode == Op_RangeCheck, "unexpected opcode")do { if (!(opcode == Op_If || opcode == Op_RangeCheck)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2616, "assert(" "opcode == Op_If || opcode == Op_RangeCheck" ") failed", "unexpected opcode"); ::breakpoint(); } } while ( 0); | ||||||
2617 | IfNode* new_if = (opcode == Op_If) ? new IfNode(proj2, bol, iff->_prob, iff->_fcnt): | ||||||
2618 | new RangeCheckNode(proj2, bol, iff->_prob, iff->_fcnt); | ||||||
2619 | register_node(new_if, loop, proj2, ddepth); | ||||||
2620 | |||||||
2621 | proj->set_req(0, new_if); // reattach | ||||||
2622 | set_idom(proj, new_if, ddepth); | ||||||
2623 | |||||||
2624 | ProjNode* new_exit = proj_clone(other_proj, new_if)->as_Proj(); | ||||||
2625 | guarantee(new_exit != NULL, "null exit node")do { if (!(new_exit != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2625, "guarantee(" "new_exit != NULL" ") failed", "null exit node" ); ::breakpoint(); } } while (0); | ||||||
2626 | register_node(new_exit, get_loop(other_proj), new_if, ddepth); | ||||||
2627 | |||||||
2628 | return new_exit; | ||||||
2629 | } | ||||||
2630 | |||||||
2631 | //------------------------------ insert_region_before_proj ------------------------------------- | ||||||
2632 | // Insert a region before an if projection (* - new node) | ||||||
2633 | // | ||||||
2634 | // before | ||||||
2635 | // if(test) | ||||||
2636 | // / | | ||||||
2637 | // v | | ||||||
2638 | // proj v | ||||||
2639 | // other-proj | ||||||
2640 | // | ||||||
2641 | // after | ||||||
2642 | // if(test) | ||||||
2643 | // / | | ||||||
2644 | // v | | ||||||
2645 | // * proj-clone v | ||||||
2646 | // | other-proj | ||||||
2647 | // v | ||||||
2648 | // * new-region | ||||||
2649 | // | | ||||||
2650 | // v | ||||||
2651 | // * dum_if | ||||||
2652 | // / \ | ||||||
2653 | // v \ | ||||||
2654 | // * dum-proj v | ||||||
2655 | // proj | ||||||
2656 | // | ||||||
2657 | RegionNode* PhaseIdealLoop::insert_region_before_proj(ProjNode* proj) { | ||||||
2658 | IfNode* iff = proj->in(0)->as_If(); | ||||||
2659 | IdealLoopTree *loop = get_loop(proj); | ||||||
2660 | ProjNode *other_proj = iff->proj_out(!proj->is_IfTrue())->as_Proj(); | ||||||
2661 | int ddepth = dom_depth(proj); | ||||||
2662 | |||||||
2663 | _igvn.rehash_node_delayed(iff); | ||||||
2664 | _igvn.rehash_node_delayed(proj); | ||||||
2665 | |||||||
2666 | proj->set_req(0, NULL__null); // temporary disconnect | ||||||
2667 | ProjNode* proj2 = proj_clone(proj, iff); | ||||||
2668 | register_node(proj2, loop, iff, ddepth); | ||||||
2669 | |||||||
2670 | RegionNode* reg = new RegionNode(2); | ||||||
2671 | reg->set_req(1, proj2); | ||||||
2672 | register_node(reg, loop, iff, ddepth); | ||||||
2673 | |||||||
2674 | IfNode* dum_if = new IfNode(reg, short_circuit_if(NULL__null, proj), iff->_prob, iff->_fcnt); | ||||||
2675 | register_node(dum_if, loop, reg, ddepth); | ||||||
2676 | |||||||
2677 | proj->set_req(0, dum_if); // reattach | ||||||
2678 | set_idom(proj, dum_if, ddepth); | ||||||
2679 | |||||||
2680 | ProjNode* dum_proj = proj_clone(other_proj, dum_if); | ||||||
2681 | register_node(dum_proj, loop, dum_if, ddepth); | ||||||
2682 | |||||||
2683 | return reg; | ||||||
2684 | } | ||||||
2685 | |||||||
2686 | //------------------------------ insert_cmpi_loop_exit ------------------------------------- | ||||||
2687 | // Clone a signed compare loop exit from an unsigned compare and | ||||||
2688 | // insert it before the unsigned cmp on the stay-in-loop path. | ||||||
2689 | // All new nodes inserted in the dominator tree between the original | ||||||
2690 | // if and it's projections. The original if test is replaced with | ||||||
2691 | // a constant to force the stay-in-loop path. | ||||||
2692 | // | ||||||
2693 | // This is done to make sure that the original if and it's projections | ||||||
2694 | // still dominate the same set of control nodes, that the ctrl() relation | ||||||
2695 | // from data nodes to them is preserved, and that their loop nesting is | ||||||
2696 | // preserved. | ||||||
2697 | // | ||||||
2698 | // before | ||||||
2699 | // if(i <u limit) unsigned compare loop exit | ||||||
2700 | // / | | ||||||
2701 | // v v | ||||||
2702 | // exit-proj stay-in-loop-proj | ||||||
2703 | // | ||||||
2704 | // after | ||||||
2705 | // if(stay-in-loop-const) original if | ||||||
2706 | // / | | ||||||
2707 | // / v | ||||||
2708 | // / if(i < limit) new signed test | ||||||
2709 | // / / | | ||||||
2710 | // / / v | ||||||
2711 | // / / if(i <u limit) new cloned unsigned test | ||||||
2712 | // / / / | | ||||||
2713 | // v v v | | ||||||
2714 | // region | | ||||||
2715 | // | | | ||||||
2716 | // dum-if | | ||||||
2717 | // / | | | ||||||
2718 | // ether | | | ||||||
2719 | // v v | ||||||
2720 | // exit-proj stay-in-loop-proj | ||||||
2721 | // | ||||||
2722 | IfNode* PhaseIdealLoop::insert_cmpi_loop_exit(IfNode* if_cmpu, IdealLoopTree *loop) { | ||||||
2723 | const bool Signed = true; | ||||||
2724 | const bool Unsigned = false; | ||||||
2725 | |||||||
2726 | BoolNode* bol = if_cmpu->in(1)->as_Bool(); | ||||||
2727 | if (bol->_test._test != BoolTest::lt) return NULL__null; | ||||||
2728 | CmpNode* cmpu = bol->in(1)->as_Cmp(); | ||||||
2729 | if (cmpu->Opcode() != Op_CmpU) return NULL__null; | ||||||
2730 | int stride = stride_of_possible_iv(if_cmpu); | ||||||
2731 | if (stride == 0) return NULL__null; | ||||||
2732 | |||||||
2733 | Node* lp_proj = stay_in_loop(if_cmpu, loop); | ||||||
2734 | guarantee(lp_proj != NULL, "null loop node")do { if (!(lp_proj != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2734, "guarantee(" "lp_proj != NULL" ") failed", "null loop node" ); ::breakpoint(); } } while (0); | ||||||
2735 | |||||||
2736 | ProjNode* lp_continue = lp_proj->as_Proj(); | ||||||
2737 | ProjNode* lp_exit = if_cmpu->proj_out(!lp_continue->is_IfTrue())->as_Proj(); | ||||||
2738 | if (!lp_exit->is_IfFalse()) { | ||||||
2739 | // The loop exit condition is (i <u limit) ==> (i >= 0 && i < limit). | ||||||
2740 | // We therefore can't add a single exit condition. | ||||||
2741 | return NULL__null; | ||||||
2742 | } | ||||||
2743 | // The loop exit condition is !(i <u limit) ==> (i < 0 || i >= limit). | ||||||
2744 | // Split out the exit condition (i < 0) for stride < 0 or (i >= limit) for stride > 0. | ||||||
2745 | Node* limit = NULL__null; | ||||||
2746 | if (stride > 0) { | ||||||
2747 | limit = cmpu->in(2); | ||||||
2748 | } else { | ||||||
2749 | limit = _igvn.makecon(TypeInt::ZERO); | ||||||
2750 | set_ctrl(limit, C->root()); | ||||||
2751 | } | ||||||
2752 | // Create a new region on the exit path | ||||||
2753 | RegionNode* reg = insert_region_before_proj(lp_exit); | ||||||
2754 | guarantee(reg != NULL, "null region node")do { if (!(reg != __null)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2754, "guarantee(" "reg != NULL" ") failed", "null region node" ); ::breakpoint(); } } while (0); | ||||||
2755 | |||||||
2756 | // Clone the if-cmpu-true-false using a signed compare | ||||||
2757 | BoolTest::mask rel_i = stride > 0 ? bol->_test._test : BoolTest::ge; | ||||||
2758 | ProjNode* cmpi_exit = insert_if_before_proj(cmpu->in(1), Signed, rel_i, limit, lp_continue); | ||||||
2759 | reg->add_req(cmpi_exit); | ||||||
2760 | |||||||
2761 | // Clone the if-cmpu-true-false | ||||||
2762 | BoolTest::mask rel_u = bol->_test._test; | ||||||
2763 | ProjNode* cmpu_exit = insert_if_before_proj(cmpu->in(1), Unsigned, rel_u, cmpu->in(2), lp_continue); | ||||||
2764 | reg->add_req(cmpu_exit); | ||||||
2765 | |||||||
2766 | // Force original if to stay in loop. | ||||||
2767 | short_circuit_if(if_cmpu, lp_continue); | ||||||
2768 | |||||||
2769 | return cmpi_exit->in(0)->as_If(); | ||||||
2770 | } | ||||||
2771 | |||||||
2772 | //------------------------------ remove_cmpi_loop_exit ------------------------------------- | ||||||
2773 | // Remove a previously inserted signed compare loop exit. | ||||||
2774 | void PhaseIdealLoop::remove_cmpi_loop_exit(IfNode* if_cmp, IdealLoopTree *loop) { | ||||||
2775 | Node* lp_proj = stay_in_loop(if_cmp, loop); | ||||||
2776 | assert(if_cmp->in(1)->in(1)->Opcode() == Op_CmpI &&do { if (!(if_cmp->in(1)->in(1)->Opcode() == Op_CmpI && stay_in_loop(lp_proj, loop)->is_If() && stay_in_loop(lp_proj, loop)->in(1)->in(1)->Opcode() == Op_CmpU)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2778, "assert(" "if_cmp->in(1)->in(1)->Opcode() == Op_CmpI && stay_in_loop(lp_proj, loop)->is_If() && stay_in_loop(lp_proj, loop)->in(1)->in(1)->Opcode() == Op_CmpU" ") failed", "inserted cmpi before cmpu"); ::breakpoint(); } } while (0) | ||||||
2777 | stay_in_loop(lp_proj, loop)->is_If() &&do { if (!(if_cmp->in(1)->in(1)->Opcode() == Op_CmpI && stay_in_loop(lp_proj, loop)->is_If() && stay_in_loop(lp_proj, loop)->in(1)->in(1)->Opcode() == Op_CmpU)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2778, "assert(" "if_cmp->in(1)->in(1)->Opcode() == Op_CmpI && stay_in_loop(lp_proj, loop)->is_If() && stay_in_loop(lp_proj, loop)->in(1)->in(1)->Opcode() == Op_CmpU" ") failed", "inserted cmpi before cmpu"); ::breakpoint(); } } while (0) | ||||||
2778 | stay_in_loop(lp_proj, loop)->in(1)->in(1)->Opcode() == Op_CmpU, "inserted cmpi before cmpu")do { if (!(if_cmp->in(1)->in(1)->Opcode() == Op_CmpI && stay_in_loop(lp_proj, loop)->is_If() && stay_in_loop(lp_proj, loop)->in(1)->in(1)->Opcode() == Op_CmpU)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2778, "assert(" "if_cmp->in(1)->in(1)->Opcode() == Op_CmpI && stay_in_loop(lp_proj, loop)->is_If() && stay_in_loop(lp_proj, loop)->in(1)->in(1)->Opcode() == Op_CmpU" ") failed", "inserted cmpi before cmpu"); ::breakpoint(); } } while (0); | ||||||
2779 | Node *con = _igvn.makecon(lp_proj->is_IfTrue() ? TypeInt::ONE : TypeInt::ZERO); | ||||||
2780 | set_ctrl(con, C->root()); | ||||||
2781 | if_cmp->set_req(1, con); | ||||||
2782 | } | ||||||
2783 | |||||||
2784 | //------------------------------ scheduled_nodelist ------------------------------------- | ||||||
2785 | // Create a post order schedule of nodes that are in the | ||||||
2786 | // "member" set. The list is returned in "sched". | ||||||
2787 | // The first node in "sched" is the loop head, followed by | ||||||
2788 | // nodes which have no inputs in the "member" set, and then | ||||||
2789 | // followed by the nodes that have an immediate input dependence | ||||||
2790 | // on a node in "sched". | ||||||
2791 | void PhaseIdealLoop::scheduled_nodelist( IdealLoopTree *loop, VectorSet& member, Node_List &sched ) { | ||||||
2792 | |||||||
2793 | assert(member.test(loop->_head->_idx), "loop head must be in member set")do { if (!(member.test(loop->_head->_idx))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2793, "assert(" "member.test(loop->_head->_idx)" ") failed" , "loop head must be in member set"); ::breakpoint(); } } while (0); | ||||||
2794 | VectorSet visited; | ||||||
2795 | Node_Stack nstack(loop->_body.size()); | ||||||
2796 | |||||||
2797 | Node* n = loop->_head; // top of stack is cached in "n" | ||||||
2798 | uint idx = 0; | ||||||
2799 | visited.set(n->_idx); | ||||||
2800 | |||||||
2801 | // Initially push all with no inputs from within member set | ||||||
2802 | for(uint i = 0; i < loop->_body.size(); i++ ) { | ||||||
2803 | Node *elt = loop->_body.at(i); | ||||||
2804 | if (member.test(elt->_idx)) { | ||||||
2805 | bool found = false; | ||||||
2806 | for (uint j = 0; j < elt->req(); j++) { | ||||||
2807 | Node* def = elt->in(j); | ||||||
2808 | if (def && member.test(def->_idx) && def != elt) { | ||||||
2809 | found = true; | ||||||
2810 | break; | ||||||
2811 | } | ||||||
2812 | } | ||||||
2813 | if (!found && elt != loop->_head) { | ||||||
2814 | nstack.push(n, idx); | ||||||
2815 | n = elt; | ||||||
2816 | assert(!visited.test(n->_idx), "not seen yet")do { if (!(!visited.test(n->_idx))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2816, "assert(" "!visited.test(n->_idx)" ") failed", "not seen yet" ); ::breakpoint(); } } while (0); | ||||||
2817 | visited.set(n->_idx); | ||||||
2818 | } | ||||||
2819 | } | ||||||
2820 | } | ||||||
2821 | |||||||
2822 | // traverse out's that are in the member set | ||||||
2823 | while (true) { | ||||||
2824 | if (idx < n->outcnt()) { | ||||||
2825 | Node* use = n->raw_out(idx); | ||||||
2826 | idx++; | ||||||
2827 | if (!visited.test_set(use->_idx)) { | ||||||
2828 | if (member.test(use->_idx)) { | ||||||
2829 | nstack.push(n, idx); | ||||||
2830 | n = use; | ||||||
2831 | idx = 0; | ||||||
2832 | } | ||||||
2833 | } | ||||||
2834 | } else { | ||||||
2835 | // All outputs processed | ||||||
2836 | sched.push(n); | ||||||
2837 | if (nstack.is_empty()) break; | ||||||
2838 | n = nstack.node(); | ||||||
2839 | idx = nstack.index(); | ||||||
2840 | nstack.pop(); | ||||||
2841 | } | ||||||
2842 | } | ||||||
2843 | } | ||||||
2844 | |||||||
2845 | |||||||
2846 | //------------------------------ has_use_in_set ------------------------------------- | ||||||
2847 | // Has a use in the vector set | ||||||
2848 | bool PhaseIdealLoop::has_use_in_set( Node* n, VectorSet& vset ) { | ||||||
2849 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | ||||||
2850 | Node* use = n->fast_out(j); | ||||||
2851 | if (vset.test(use->_idx)) { | ||||||
2852 | return true; | ||||||
2853 | } | ||||||
2854 | } | ||||||
2855 | return false; | ||||||
2856 | } | ||||||
2857 | |||||||
2858 | |||||||
2859 | //------------------------------ has_use_internal_to_set ------------------------------------- | ||||||
2860 | // Has use internal to the vector set (ie. not in a phi at the loop head) | ||||||
2861 | bool PhaseIdealLoop::has_use_internal_to_set( Node* n, VectorSet& vset, IdealLoopTree *loop ) { | ||||||
2862 | Node* head = loop->_head; | ||||||
2863 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | ||||||
2864 | Node* use = n->fast_out(j); | ||||||
2865 | if (vset.test(use->_idx) && !(use->is_Phi() && use->in(0) == head)) { | ||||||
2866 | return true; | ||||||
2867 | } | ||||||
2868 | } | ||||||
2869 | return false; | ||||||
2870 | } | ||||||
2871 | |||||||
2872 | |||||||
2873 | //------------------------------ clone_for_use_outside_loop ------------------------------------- | ||||||
2874 | // clone "n" for uses that are outside of loop | ||||||
2875 | int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) { | ||||||
2876 | int cloned = 0; | ||||||
2877 | assert(worklist.size() == 0, "should be empty")do { if (!(worklist.size() == 0)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2877, "assert(" "worklist.size() == 0" ") failed", "should be empty" ); ::breakpoint(); } } while (0); | ||||||
2878 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | ||||||
2879 | Node* use = n->fast_out(j); | ||||||
2880 | if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) { | ||||||
2881 | worklist.push(use); | ||||||
2882 | } | ||||||
2883 | } | ||||||
2884 | |||||||
2885 | if (C->check_node_count(worklist.size() + NodeLimitFudgeFactor, | ||||||
2886 | "Too many clones required in clone_for_use_outside_loop in partial peeling")) { | ||||||
2887 | return -1; | ||||||
2888 | } | ||||||
2889 | |||||||
2890 | while( worklist.size() ) { | ||||||
2891 | Node *use = worklist.pop(); | ||||||
2892 | if (!has_node(use) || use->in(0) == C->top()) continue; | ||||||
2893 | uint j; | ||||||
2894 | for (j = 0; j < use->req(); j++) { | ||||||
2895 | if (use->in(j) == n) break; | ||||||
2896 | } | ||||||
2897 | assert(j < use->req(), "must be there")do { if (!(j < use->req())) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2897, "assert(" "j < use->req()" ") failed", "must be there" ); ::breakpoint(); } } while (0); | ||||||
2898 | |||||||
2899 | // clone "n" and insert it between the inputs of "n" and the use outside the loop | ||||||
2900 | Node* n_clone = n->clone(); | ||||||
2901 | _igvn.replace_input_of(use, j, n_clone); | ||||||
2902 | cloned++; | ||||||
2903 | Node* use_c; | ||||||
2904 | if (!use->is_Phi()) { | ||||||
2905 | use_c = has_ctrl(use) ? get_ctrl(use) : use->in(0); | ||||||
2906 | } else { | ||||||
2907 | // Use in a phi is considered a use in the associated predecessor block | ||||||
2908 | use_c = use->in(0)->in(j); | ||||||
2909 | } | ||||||
2910 | set_ctrl(n_clone, use_c); | ||||||
2911 | assert(!loop->is_member(get_loop(use_c)), "should be outside loop")do { if (!(!loop->is_member(get_loop(use_c)))) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2911, "assert(" "!loop->is_member(get_loop(use_c))" ") failed" , "should be outside loop"); ::breakpoint(); } } while (0); | ||||||
2912 | get_loop(use_c)->_body.push(n_clone); | ||||||
2913 | _igvn.register_new_node_with_optimizer(n_clone); | ||||||
2914 | #ifndef PRODUCT | ||||||
2915 | if (TracePartialPeeling) { | ||||||
2916 | tty->print_cr("loop exit cloning old: %d new: %d newbb: %d", n->_idx, n_clone->_idx, get_ctrl(n_clone)->_idx); | ||||||
2917 | } | ||||||
2918 | #endif | ||||||
2919 | } | ||||||
2920 | return cloned; | ||||||
2921 | } | ||||||
2922 | |||||||
2923 | |||||||
2924 | //------------------------------ clone_for_special_use_inside_loop ------------------------------------- | ||||||
2925 | // clone "n" for special uses that are in the not_peeled region. | ||||||
2926 | // If these def-uses occur in separate blocks, the code generator | ||||||
2927 | // marks the method as not compilable. For example, if a "BoolNode" | ||||||
2928 | // is in a different basic block than the "IfNode" that uses it, then | ||||||
2929 | // the compilation is aborted in the code generator. | ||||||
2930 | void PhaseIdealLoop::clone_for_special_use_inside_loop( IdealLoopTree *loop, Node* n, | ||||||
2931 | VectorSet& not_peel, Node_List& sink_list, Node_List& worklist ) { | ||||||
2932 | if (n->is_Phi() || n->is_Load()) { | ||||||
2933 | return; | ||||||
2934 | } | ||||||
2935 | assert(worklist.size() == 0, "should be empty")do { if (!(worklist.size() == 0)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 2935, "assert(" "worklist.size() == 0" ") failed", "should be empty" ); ::breakpoint(); } } while (0); | ||||||
2936 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | ||||||
2937 | Node* use = n->fast_out(j); | ||||||
2938 | if ( not_peel.test(use->_idx) && | ||||||
2939 | (use->is_If() || use->is_CMove() || use->is_Bool()) && | ||||||
2940 | use->in(1) == n) { | ||||||
2941 | worklist.push(use); | ||||||
2942 | } | ||||||
2943 | } | ||||||
2944 | if (worklist.size() > 0) { | ||||||
2945 | // clone "n" and insert it between inputs of "n" and the use | ||||||
2946 | Node* n_clone = n->clone(); | ||||||
2947 | loop->_body.push(n_clone); | ||||||
2948 | _igvn.register_new_node_with_optimizer(n_clone); | ||||||
2949 | set_ctrl(n_clone, get_ctrl(n)); | ||||||
2950 | sink_list.push(n_clone); | ||||||
2951 | not_peel.set(n_clone->_idx); | ||||||
2952 | #ifndef PRODUCT | ||||||
2953 | if (TracePartialPeeling) { | ||||||
2954 | tty->print_cr("special not_peeled cloning old: %d new: %d", n->_idx, n_clone->_idx); | ||||||
2955 | } | ||||||
2956 | #endif | ||||||
2957 | while( worklist.size() ) { | ||||||
2958 | Node *use = worklist.pop(); | ||||||
2959 | _igvn.rehash_node_delayed(use); | ||||||
2960 | for (uint j = 1; j < use->req(); j++) { | ||||||
2961 | if (use->in(j) == n) { | ||||||
2962 | use->set_req(j, n_clone); | ||||||
2963 | } | ||||||
2964 | } | ||||||
2965 | } | ||||||
2966 | } | ||||||
2967 | } | ||||||
2968 | |||||||
2969 | |||||||
2970 | //------------------------------ insert_phi_for_loop ------------------------------------- | ||||||
2971 | // Insert phi(lp_entry_val, back_edge_val) at use->in(idx) for loop lp if phi does not already exist | ||||||
2972 | void PhaseIdealLoop::insert_phi_for_loop( Node* use, uint idx, Node* lp_entry_val, Node* back_edge_val, LoopNode* lp ) { | ||||||
2973 | Node *phi = PhiNode::make(lp, back_edge_val); | ||||||
2974 | phi->set_req(LoopNode::EntryControl, lp_entry_val); | ||||||
2975 | // Use existing phi if it already exists | ||||||
2976 | Node *hit = _igvn.hash_find_insert(phi); | ||||||
2977 | if( hit == NULL__null ) { | ||||||
2978 | _igvn.register_new_node_with_optimizer(phi); | ||||||
2979 | set_ctrl(phi, lp); | ||||||
2980 | } else { | ||||||
2981 | // Remove the new phi from the graph and use the hit | ||||||
2982 | _igvn.remove_dead_node(phi); | ||||||
2983 | phi = hit; | ||||||
2984 | } | ||||||
2985 | _igvn.replace_input_of(use, idx, phi); | ||||||
2986 | } | ||||||
2987 | |||||||
2988 | #ifdef ASSERT1 | ||||||
2989 | //------------------------------ is_valid_loop_partition ------------------------------------- | ||||||
2990 | // Validate the loop partition sets: peel and not_peel | ||||||
2991 | bool PhaseIdealLoop::is_valid_loop_partition( IdealLoopTree *loop, VectorSet& peel, Node_List& peel_list, | ||||||
2992 | VectorSet& not_peel ) { | ||||||
2993 | uint i; | ||||||
2994 | // Check that peel_list entries are in the peel set | ||||||
2995 | for (i = 0; i < peel_list.size(); i++) { | ||||||
2996 | if (!peel.test(peel_list.at(i)->_idx)) { | ||||||
2997 | return false; | ||||||
2998 | } | ||||||
2999 | } | ||||||
3000 | // Check at loop members are in one of peel set or not_peel set | ||||||
3001 | for (i = 0; i < loop->_body.size(); i++ ) { | ||||||
3002 | Node *def = loop->_body.at(i); | ||||||
3003 | uint di = def->_idx; | ||||||
3004 | // Check that peel set elements are in peel_list | ||||||
3005 | if (peel.test(di)) { | ||||||
3006 | if (not_peel.test(di)) { | ||||||
3007 | return false; | ||||||
3008 | } | ||||||
3009 | // Must be in peel_list also | ||||||
3010 | bool found = false; | ||||||
3011 | for (uint j = 0; j < peel_list.size(); j++) { | ||||||
3012 | if (peel_list.at(j)->_idx == di) { | ||||||
3013 | found = true; | ||||||
3014 | break; | ||||||
3015 | } | ||||||
3016 | } | ||||||
3017 | if (!found) { | ||||||
3018 | return false; | ||||||
3019 | } | ||||||
3020 | } else if (not_peel.test(di)) { | ||||||
3021 | if (peel.test(di)) { | ||||||
3022 | return false; | ||||||
3023 | } | ||||||
3024 | } else { | ||||||
3025 | return false; | ||||||
3026 | } | ||||||
3027 | } | ||||||
3028 | return true; | ||||||
3029 | } | ||||||
3030 | |||||||
3031 | //------------------------------ is_valid_clone_loop_exit_use ------------------------------------- | ||||||
3032 | // Ensure a use outside of loop is of the right form | ||||||
3033 | bool PhaseIdealLoop::is_valid_clone_loop_exit_use( IdealLoopTree *loop, Node* use, uint exit_idx) { | ||||||
3034 | Node *use_c = has_ctrl(use) ? get_ctrl(use) : use; | ||||||
3035 | return (use->is_Phi() && | ||||||
3036 | use_c->is_Region() && use_c->req() == 3 && | ||||||
3037 | (use_c->in(exit_idx)->Opcode() == Op_IfTrue || | ||||||
3038 | use_c->in(exit_idx)->Opcode() == Op_IfFalse || | ||||||
3039 | use_c->in(exit_idx)->Opcode() == Op_JumpProj) && | ||||||
3040 | loop->is_member( get_loop( use_c->in(exit_idx)->in(0) ) ) ); | ||||||
3041 | } | ||||||
3042 | |||||||
3043 | //------------------------------ is_valid_clone_loop_form ------------------------------------- | ||||||
3044 | // Ensure that all uses outside of loop are of the right form | ||||||
3045 | bool PhaseIdealLoop::is_valid_clone_loop_form( IdealLoopTree *loop, Node_List& peel_list, | ||||||
3046 | uint orig_exit_idx, uint clone_exit_idx) { | ||||||
3047 | uint len = peel_list.size(); | ||||||
3048 | for (uint i = 0; i < len; i++) { | ||||||
3049 | Node *def = peel_list.at(i); | ||||||
3050 | |||||||
3051 | for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) { | ||||||
3052 | Node *use = def->fast_out(j); | ||||||
3053 | Node *use_c = has_ctrl(use) ? get_ctrl(use) : use; | ||||||
3054 | if (!loop->is_member(get_loop(use_c))) { | ||||||
3055 | // use is not in the loop, check for correct structure | ||||||
3056 | if (use->in(0) == def) { | ||||||
3057 | // Okay | ||||||
3058 | } else if (!is_valid_clone_loop_exit_use(loop, use, orig_exit_idx)) { | ||||||
3059 | return false; | ||||||
3060 | } | ||||||
3061 | } | ||||||
3062 | } | ||||||
3063 | } | ||||||
3064 | return true; | ||||||
3065 | } | ||||||
3066 | #endif | ||||||
3067 | |||||||
3068 | //------------------------------ partial_peel ------------------------------------- | ||||||
3069 | // Partially peel (aka loop rotation) the top portion of a loop (called | ||||||
3070 | // the peel section below) by cloning it and placing one copy just before | ||||||
3071 | // the new loop head and the other copy at the bottom of the new loop. | ||||||
3072 | // | ||||||
3073 | // before after where it came from | ||||||
3074 | // | ||||||
3075 | // stmt1 stmt1 | ||||||
3076 | // loop: stmt2 clone | ||||||
3077 | // stmt2 if condA goto exitA clone | ||||||
3078 | // if condA goto exitA new_loop: new | ||||||
3079 | // stmt3 stmt3 clone | ||||||
3080 | // if !condB goto loop if condB goto exitB clone | ||||||
3081 | // exitB: stmt2 orig | ||||||
3082 | // stmt4 if !condA goto new_loop orig | ||||||
3083 | // exitA: goto exitA | ||||||
3084 | // exitB: | ||||||
3085 | // stmt4 | ||||||
3086 | // exitA: | ||||||
3087 | // | ||||||
3088 | // Step 1: find the cut point: an exit test on probable | ||||||
3089 | // induction variable. | ||||||
3090 | // Step 2: schedule (with cloning) operations in the peel | ||||||
3091 | // section that can be executed after the cut into | ||||||
3092 | // the section that is not peeled. This may need | ||||||
3093 | // to clone operations into exit blocks. For | ||||||
3094 | // instance, a reference to A[i] in the not-peel | ||||||
3095 | // section and a reference to B[i] in an exit block | ||||||
3096 | // may cause a left-shift of i by 2 to be placed | ||||||
3097 | // in the peel block. This step will clone the left | ||||||
3098 | // shift into the exit block and sink the left shift | ||||||
3099 | // from the peel to the not-peel section. | ||||||
3100 | // Step 3: clone the loop, retarget the control, and insert | ||||||
3101 | // phis for values that are live across the new loop | ||||||
3102 | // head. This is very dependent on the graph structure | ||||||
3103 | // from clone_loop. It creates region nodes for | ||||||
3104 | // exit control and associated phi nodes for values | ||||||
3105 | // flow out of the loop through that exit. The region | ||||||
3106 | // node is dominated by the clone's control projection. | ||||||
3107 | // So the clone's peel section is placed before the | ||||||
3108 | // new loop head, and the clone's not-peel section is | ||||||
3109 | // forms the top part of the new loop. The original | ||||||
3110 | // peel section forms the tail of the new loop. | ||||||
3111 | // Step 4: update the dominator tree and recompute the | ||||||
3112 | // dominator depth. | ||||||
3113 | // | ||||||
3114 | // orig | ||||||
3115 | // | ||||||
3116 | // stmt1 | ||||||
3117 | // | | ||||||
3118 | // v | ||||||
3119 | // loop predicate | ||||||
3120 | // | | ||||||
3121 | // v | ||||||
3122 | // loop<----+ | ||||||
3123 | // | | | ||||||
3124 | // stmt2 | | ||||||
3125 | // | | | ||||||
3126 | // v | | ||||||
3127 | // ifA | | ||||||
3128 | // / | | | ||||||
3129 | // v v | | ||||||
3130 | // false true ^ <-- last_peel | ||||||
3131 | // / | | | ||||||
3132 | // / ===|==cut | | ||||||
3133 | // / stmt3 | <-- first_not_peel | ||||||
3134 | // / | | | ||||||
3135 | // | v | | ||||||
3136 | // v ifB | | ||||||
3137 | // exitA: / \ | | ||||||
3138 | // / \ | | ||||||
3139 | // v v | | ||||||
3140 | // false true | | ||||||
3141 | // / \ | | ||||||
3142 | // / ----+ | ||||||
3143 | // | | ||||||
3144 | // v | ||||||
3145 | // exitB: | ||||||
3146 | // stmt4 | ||||||
3147 | // | ||||||
3148 | // | ||||||
3149 | // after clone loop | ||||||
3150 | // | ||||||
3151 | // stmt1 | ||||||
3152 | // | | ||||||
3153 | // v | ||||||
3154 | // loop predicate | ||||||
3155 | // / \ | ||||||
3156 | // clone / \ orig | ||||||
3157 | // / \ | ||||||
3158 | // / \ | ||||||
3159 | // v v | ||||||
3160 | // +---->loop loop<----+ | ||||||
3161 | // | | | | | ||||||
3162 | // | stmt2 stmt2 | | ||||||
3163 | // | | | | | ||||||
3164 | // | v v | | ||||||
3165 | // | ifA ifA | | ||||||
3166 | // | | \ / | | | ||||||
3167 | // | v v v v | | ||||||
3168 | // ^ true false false true ^ <-- last_peel | ||||||
3169 | // | | ^ \ / | | | ||||||
3170 | // | cut==|== \ \ / ===|==cut | | ||||||
3171 | // | stmt3 \ \ / stmt3 | <-- first_not_peel | ||||||
3172 | // | | dom | | | | | ||||||
3173 | // | v \ 1v v2 v | | ||||||
3174 | // | ifB regionA ifB | | ||||||
3175 | // | / \ | / \ | | ||||||
3176 | // | / \ v / \ | | ||||||
3177 | // | v v exitA: v v | | ||||||
3178 | // | true false false true | | ||||||
3179 | // | / ^ \ / \ | | ||||||
3180 | // +---- \ \ / ----+ | ||||||
3181 | // dom \ / | ||||||
3182 | // \ 1v v2 | ||||||
3183 | // regionB | ||||||
3184 | // | | ||||||
3185 | // v | ||||||
3186 | // exitB: | ||||||
3187 | // stmt4 | ||||||
3188 | // | ||||||
3189 | // | ||||||
3190 | // after partial peel | ||||||
3191 | // | ||||||
3192 | // stmt1 | ||||||
3193 | // | | ||||||
3194 | // v | ||||||
3195 | // loop predicate | ||||||
3196 | // / | ||||||
3197 | // clone / orig | ||||||
3198 | // / TOP | ||||||
3199 | // / \ | ||||||
3200 | // v v | ||||||
3201 | // TOP->loop loop----+ | ||||||
3202 | // | | | | ||||||
3203 | // stmt2 stmt2 | | ||||||
3204 | // | | | | ||||||
3205 | // v v | | ||||||
3206 | // ifA ifA | | ||||||
3207 | // | \ / | | | ||||||
3208 | // v v v v | | ||||||
3209 | // true false false true | <-- last_peel | ||||||
3210 | // | ^ \ / +------|---+ | ||||||
3211 | // +->newloop \ \ / === ==cut | | | ||||||
3212 | // | stmt3 \ \ / TOP | | | ||||||
3213 | // | | dom | | stmt3 | | <-- first_not_peel | ||||||
3214 | // | v \ 1v v2 v | | | ||||||
3215 | // | ifB regionA ifB ^ v | ||||||
3216 | // | / \ | / \ | | | ||||||
3217 | // | / \ v / \ | | | ||||||
3218 | // | v v exitA: v v | | | ||||||
3219 | // | true false false true | | | ||||||
3220 | // | / ^ \ / \ | | | ||||||
3221 | // | | \ \ / v | | | ||||||
3222 | // | | dom \ / TOP | | | ||||||
3223 | // | | \ 1v v2 | | | ||||||
3224 | // ^ v regionB | | | ||||||
3225 | // | | | | | | ||||||
3226 | // | | v ^ v | ||||||
3227 | // | | exitB: | | | ||||||
3228 | // | | stmt4 | | | ||||||
3229 | // | +------------>-----------------+ | | ||||||
3230 | // | | | ||||||
3231 | // +-----------------<---------------------+ | ||||||
3232 | // | ||||||
3233 | // | ||||||
3234 | // final graph | ||||||
3235 | // | ||||||
3236 | // stmt1 | ||||||
3237 | // | | ||||||
3238 | // v | ||||||
3239 | // loop predicate | ||||||
3240 | // | | ||||||
3241 | // v | ||||||
3242 | // stmt2 clone | ||||||
3243 | // | | ||||||
3244 | // v | ||||||
3245 | // ........> ifA clone | ||||||
3246 | // : / | | ||||||
3247 | // dom / | | ||||||
3248 | // : v v | ||||||
3249 | // : false true | ||||||
3250 | // : | | | ||||||
3251 | // : | v | ||||||
3252 | // : | newloop<-----+ | ||||||
3253 | // : | | | | ||||||
3254 | // : | stmt3 clone | | ||||||
3255 | // : | | | | ||||||
3256 | // : | v | | ||||||
3257 | // : | ifB | | ||||||
3258 | // : | / \ | | ||||||
3259 | // : | v v | | ||||||
3260 | // : | false true | | ||||||
3261 | // : | | | | | ||||||
3262 | // : | v stmt2 | | ||||||
3263 | // : | exitB: | | | ||||||
3264 | // : | stmt4 v | | ||||||
3265 | // : | ifA orig | | ||||||
3266 | // : | / \ | | ||||||
3267 | // : | / \ | | ||||||
3268 | // : | v v | | ||||||
3269 | // : | false true | | ||||||
3270 | // : | / \ | | ||||||
3271 | // : v v -----+ | ||||||
3272 | // RegionA | ||||||
3273 | // | | ||||||
3274 | // v | ||||||
3275 | // exitA | ||||||
3276 | // | ||||||
3277 | bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) { | ||||||
3278 | |||||||
3279 | assert(!loop->_head->is_CountedLoop(), "Non-counted loop only")do { if (!(!loop->_head->is_CountedLoop())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3279, "assert(" "!loop->_head->is_CountedLoop()" ") failed" , "Non-counted loop only"); ::breakpoint(); } } while (0); | ||||||
3280 | if (!loop->_head->is_Loop()) { | ||||||
3281 | return false; | ||||||
3282 | } | ||||||
3283 | LoopNode *head = loop->_head->as_Loop(); | ||||||
3284 | |||||||
3285 | if (head->is_partial_peel_loop() || head->partial_peel_has_failed()) { | ||||||
3286 | return false; | ||||||
3287 | } | ||||||
3288 | |||||||
3289 | // Check for complex exit control | ||||||
3290 | for (uint ii = 0; ii < loop->_body.size(); ii++) { | ||||||
3291 | Node *n = loop->_body.at(ii); | ||||||
3292 | int opc = n->Opcode(); | ||||||
3293 | if (n->is_Call() || | ||||||
3294 | opc == Op_Catch || | ||||||
3295 | opc == Op_CatchProj || | ||||||
3296 | opc == Op_Jump || | ||||||
3297 | opc == Op_JumpProj) { | ||||||
3298 | #ifndef PRODUCT | ||||||
3299 | if (TracePartialPeeling) { | ||||||
3300 | tty->print_cr("\nExit control too complex: lp: %d", head->_idx); | ||||||
3301 | } | ||||||
3302 | #endif | ||||||
3303 | return false; | ||||||
3304 | } | ||||||
3305 | } | ||||||
3306 | |||||||
3307 | int dd = dom_depth(head); | ||||||
3308 | |||||||
3309 | // Step 1: find cut point | ||||||
3310 | |||||||
3311 | // Walk up dominators to loop head looking for first loop exit | ||||||
3312 | // which is executed on every path thru loop. | ||||||
3313 | IfNode *peel_if = NULL__null; | ||||||
3314 | IfNode *peel_if_cmpu = NULL__null; | ||||||
3315 | |||||||
3316 | Node *iff = loop->tail(); | ||||||
3317 | while (iff != head) { | ||||||
3318 | if (iff->is_If()) { | ||||||
3319 | Node *ctrl = get_ctrl(iff->in(1)); | ||||||
3320 | if (ctrl->is_top()) return false; // Dead test on live IF. | ||||||
3321 | // If loop-varying exit-test, check for induction variable | ||||||
3322 | if (loop->is_member(get_loop(ctrl)) && | ||||||
3323 | loop->is_loop_exit(iff) && | ||||||
3324 | is_possible_iv_test(iff)) { | ||||||
3325 | Node* cmp = iff->in(1)->in(1); | ||||||
3326 | if (cmp->Opcode() == Op_CmpI) { | ||||||
3327 | peel_if = iff->as_If(); | ||||||
3328 | } else { | ||||||
3329 | assert(cmp->Opcode() == Op_CmpU, "must be CmpI or CmpU")do { if (!(cmp->Opcode() == Op_CmpU)) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3329, "assert(" "cmp->Opcode() == Op_CmpU" ") failed", "must be CmpI or CmpU" ); ::breakpoint(); } } while (0); | ||||||
3330 | peel_if_cmpu = iff->as_If(); | ||||||
3331 | } | ||||||
3332 | } | ||||||
3333 | } | ||||||
3334 | iff = idom(iff); | ||||||
3335 | } | ||||||
3336 | |||||||
3337 | // Prefer signed compare over unsigned compare. | ||||||
3338 | IfNode* new_peel_if = NULL__null; | ||||||
3339 | if (peel_if == NULL__null) { | ||||||
3340 | if (!PartialPeelAtUnsignedTests || peel_if_cmpu == NULL__null) { | ||||||
3341 | return false; // No peel point found | ||||||
3342 | } | ||||||
3343 | new_peel_if = insert_cmpi_loop_exit(peel_if_cmpu, loop); | ||||||
3344 | if (new_peel_if == NULL__null) { | ||||||
3345 | return false; // No peel point found | ||||||
3346 | } | ||||||
3347 | peel_if = new_peel_if; | ||||||
3348 | } | ||||||
3349 | Node* last_peel = stay_in_loop(peel_if, loop); | ||||||
3350 | Node* first_not_peeled = stay_in_loop(last_peel, loop); | ||||||
3351 | if (first_not_peeled == NULL__null || first_not_peeled == head) { | ||||||
3352 | return false; | ||||||
3353 | } | ||||||
3354 | |||||||
3355 | #ifndef PRODUCT | ||||||
3356 | if (TraceLoopOpts) { | ||||||
3357 | tty->print("PartialPeel "); | ||||||
3358 | loop->dump_head(); | ||||||
3359 | } | ||||||
3360 | |||||||
3361 | if (TracePartialPeeling) { | ||||||
3362 | tty->print_cr("before partial peel one iteration"); | ||||||
3363 | Node_List wl; | ||||||
3364 | Node* t = head->in(2); | ||||||
3365 | while (true) { | ||||||
3366 | wl.push(t); | ||||||
3367 | if (t == head) break; | ||||||
3368 | t = idom(t); | ||||||
3369 | } | ||||||
3370 | while (wl.size() > 0) { | ||||||
3371 | Node* tt = wl.pop(); | ||||||
3372 | tt->dump(); | ||||||
3373 | if (tt == last_peel) tty->print_cr("-- cut --"); | ||||||
3374 | } | ||||||
3375 | } | ||||||
3376 | #endif | ||||||
3377 | VectorSet peel; | ||||||
3378 | VectorSet not_peel; | ||||||
3379 | Node_List peel_list; | ||||||
3380 | Node_List worklist; | ||||||
3381 | Node_List sink_list; | ||||||
3382 | |||||||
3383 | uint estimate = loop->est_loop_clone_sz(1); | ||||||
3384 | if (exceeding_node_budget(estimate)) { | ||||||
3385 | return false; | ||||||
3386 | } | ||||||
3387 | |||||||
3388 | // Set of cfg nodes to peel are those that are executable from | ||||||
3389 | // the head through last_peel. | ||||||
3390 | assert(worklist.size() == 0, "should be empty")do { if (!(worklist.size() == 0)) { (*g_assert_poison) = 'X'; ; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3390, "assert(" "worklist.size() == 0" ") failed", "should be empty" ); ::breakpoint(); } } while (0); | ||||||
3391 | worklist.push(head); | ||||||
3392 | peel.set(head->_idx); | ||||||
3393 | while (worklist.size() > 0) { | ||||||
3394 | Node *n = worklist.pop(); | ||||||
3395 | if (n != last_peel) { | ||||||
3396 | for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { | ||||||
3397 | Node* use = n->fast_out(j); | ||||||
3398 | if (use->is_CFG() && | ||||||
3399 | loop->is_member(get_loop(use)) && | ||||||
3400 | !peel.test_set(use->_idx)) { | ||||||
3401 | worklist.push(use); | ||||||
3402 | } | ||||||
3403 | } | ||||||
3404 | } | ||||||
3405 | } | ||||||
3406 | |||||||
3407 | // Set of non-cfg nodes to peel are those that are control | ||||||
3408 | // dependent on the cfg nodes. | ||||||
3409 | for (uint i = 0; i < loop->_body.size(); i++) { | ||||||
3410 | Node *n = loop->_body.at(i); | ||||||
3411 | Node *n_c = has_ctrl(n) ? get_ctrl(n) : n; | ||||||
3412 | if (peel.test(n_c->_idx)) { | ||||||
3413 | peel.set(n->_idx); | ||||||
3414 | } else { | ||||||
3415 | not_peel.set(n->_idx); | ||||||
3416 | } | ||||||
3417 | } | ||||||
3418 | |||||||
3419 | // Step 2: move operations from the peeled section down into the | ||||||
3420 | // not-peeled section | ||||||
3421 | |||||||
3422 | // Get a post order schedule of nodes in the peel region | ||||||
3423 | // Result in right-most operand. | ||||||
3424 | scheduled_nodelist(loop, peel, peel_list); | ||||||
3425 | |||||||
3426 | assert(is_valid_loop_partition(loop, peel, peel_list, not_peel), "bad partition")do { if (!(is_valid_loop_partition(loop, peel, peel_list, not_peel ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3426, "assert(" "is_valid_loop_partition(loop, peel, peel_list, not_peel)" ") failed", "bad partition"); ::breakpoint(); } } while (0); | ||||||
3427 | |||||||
3428 | // For future check for too many new phis | ||||||
3429 | uint old_phi_cnt = 0; | ||||||
3430 | for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) { | ||||||
3431 | Node* use = head->fast_out(j); | ||||||
3432 | if (use->is_Phi()) old_phi_cnt++; | ||||||
3433 | } | ||||||
3434 | |||||||
3435 | #ifndef PRODUCT | ||||||
3436 | if (TracePartialPeeling) { | ||||||
3437 | tty->print_cr("\npeeled list"); | ||||||
3438 | } | ||||||
3439 | #endif | ||||||
3440 | |||||||
3441 | // Evacuate nodes in peel region into the not_peeled region if possible | ||||||
3442 | bool too_many_clones = false; | ||||||
3443 | uint new_phi_cnt = 0; | ||||||
3444 | uint cloned_for_outside_use = 0; | ||||||
3445 | for (uint i = 0; i < peel_list.size();) { | ||||||
3446 | Node* n = peel_list.at(i); | ||||||
3447 | #ifndef PRODUCT | ||||||
3448 | if (TracePartialPeeling) n->dump(); | ||||||
3449 | #endif | ||||||
3450 | bool incr = true; | ||||||
3451 | if (!n->is_CFG()) { | ||||||
3452 | if (has_use_in_set(n, not_peel)) { | ||||||
3453 | // If not used internal to the peeled region, | ||||||
3454 | // move "n" from peeled to not_peeled region. | ||||||
3455 | if (!has_use_internal_to_set(n, peel, loop)) { | ||||||
3456 | // if not pinned and not a load (which maybe anti-dependent on a store) | ||||||
3457 | // and not a CMove (Matcher expects only bool->cmove). | ||||||
3458 | if (n->in(0) == NULL__null && !n->is_Load() && !n->is_CMove()) { | ||||||
3459 | int new_clones = clone_for_use_outside_loop(loop, n, worklist); | ||||||
3460 | if (new_clones == -1) { | ||||||
3461 | too_many_clones = true; | ||||||
3462 | break; | ||||||
3463 | } | ||||||
3464 | cloned_for_outside_use += new_clones; | ||||||
3465 | sink_list.push(n); | ||||||
3466 | peel.remove(n->_idx); | ||||||
3467 | not_peel.set(n->_idx); | ||||||
3468 | peel_list.remove(i); | ||||||
3469 | incr = false; | ||||||
3470 | #ifndef PRODUCT | ||||||
3471 | if (TracePartialPeeling) { | ||||||
3472 | tty->print_cr("sink to not_peeled region: %d newbb: %d", | ||||||
3473 | n->_idx, get_ctrl(n)->_idx); | ||||||
3474 | } | ||||||
3475 | #endif | ||||||
3476 | } | ||||||
3477 | } else { | ||||||
3478 | // Otherwise check for special def-use cases that span | ||||||
3479 | // the peel/not_peel boundary such as bool->if | ||||||
3480 | clone_for_special_use_inside_loop(loop, n, not_peel, sink_list, worklist); | ||||||
3481 | new_phi_cnt++; | ||||||
3482 | } | ||||||
3483 | } | ||||||
3484 | } | ||||||
3485 | if (incr) i++; | ||||||
3486 | } | ||||||
3487 | |||||||
3488 | estimate += cloned_for_outside_use + new_phi_cnt; | ||||||
3489 | bool exceed_node_budget = !may_require_nodes(estimate); | ||||||
3490 | bool exceed_phi_limit = new_phi_cnt > old_phi_cnt + PartialPeelNewPhiDelta; | ||||||
3491 | |||||||
3492 | if (too_many_clones || exceed_node_budget || exceed_phi_limit) { | ||||||
3493 | #ifndef PRODUCT | ||||||
3494 | if (TracePartialPeeling && exceed_phi_limit) { | ||||||
3495 | tty->print_cr("\nToo many new phis: %d old %d new cmpi: %c", | ||||||
3496 | new_phi_cnt, old_phi_cnt, new_peel_if != NULL__null?'T':'F'); | ||||||
3497 | } | ||||||
3498 | #endif | ||||||
3499 | if (new_peel_if != NULL__null) { | ||||||
3500 | remove_cmpi_loop_exit(new_peel_if, loop); | ||||||
3501 | } | ||||||
3502 | // Inhibit more partial peeling on this loop | ||||||
3503 | assert(!head->is_partial_peel_loop(), "not partial peeled")do { if (!(!head->is_partial_peel_loop())) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3503, "assert(" "!head->is_partial_peel_loop()" ") failed" , "not partial peeled"); ::breakpoint(); } } while (0); | ||||||
3504 | head->mark_partial_peel_failed(); | ||||||
3505 | if (cloned_for_outside_use > 0) { | ||||||
3506 | // Terminate this round of loop opts because | ||||||
3507 | // the graph outside this loop was changed. | ||||||
3508 | C->set_major_progress(); | ||||||
3509 | return true; | ||||||
3510 | } | ||||||
3511 | return false; | ||||||
3512 | } | ||||||
3513 | |||||||
3514 | // Step 3: clone loop, retarget control, and insert new phis | ||||||
3515 | |||||||
3516 | // Create new loop head for new phis and to hang | ||||||
3517 | // the nodes being moved (sinked) from the peel region. | ||||||
3518 | LoopNode* new_head = new LoopNode(last_peel, last_peel); | ||||||
3519 | new_head->set_unswitch_count(head->unswitch_count()); // Preserve | ||||||
3520 | _igvn.register_new_node_with_optimizer(new_head); | ||||||
3521 | assert(first_not_peeled->in(0) == last_peel, "last_peel <- first_not_peeled")do { if (!(first_not_peeled->in(0) == last_peel)) { (*g_assert_poison ) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3521, "assert(" "first_not_peeled->in(0) == last_peel" ") failed" , "last_peel <- first_not_peeled"); ::breakpoint(); } } while (0); | ||||||
3522 | _igvn.replace_input_of(first_not_peeled, 0, new_head); | ||||||
3523 | set_loop(new_head, loop); | ||||||
3524 | loop->_body.push(new_head); | ||||||
3525 | not_peel.set(new_head->_idx); | ||||||
3526 | set_idom(new_head, last_peel, dom_depth(first_not_peeled)); | ||||||
3527 | set_idom(first_not_peeled, new_head, dom_depth(first_not_peeled)); | ||||||
3528 | |||||||
3529 | while (sink_list.size() > 0) { | ||||||
3530 | Node* n = sink_list.pop(); | ||||||
3531 | set_ctrl(n, new_head); | ||||||
3532 | } | ||||||
3533 | |||||||
3534 | assert(is_valid_loop_partition(loop, peel, peel_list, not_peel), "bad partition")do { if (!(is_valid_loop_partition(loop, peel, peel_list, not_peel ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3534, "assert(" "is_valid_loop_partition(loop, peel, peel_list, not_peel)" ") failed", "bad partition"); ::breakpoint(); } } while (0); | ||||||
3535 | |||||||
3536 | clone_loop(loop, old_new, dd, IgnoreStripMined); | ||||||
3537 | |||||||
3538 | const uint clone_exit_idx = 1; | ||||||
3539 | const uint orig_exit_idx = 2; | ||||||
3540 | assert(is_valid_clone_loop_form(loop, peel_list, orig_exit_idx, clone_exit_idx), "bad clone loop")do { if (!(is_valid_clone_loop_form(loop, peel_list, orig_exit_idx , clone_exit_idx))) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3540, "assert(" "is_valid_clone_loop_form(loop, peel_list, orig_exit_idx, clone_exit_idx)" ") failed", "bad clone loop"); ::breakpoint(); } } while (0); | ||||||
3541 | |||||||
3542 | Node* head_clone = old_new[head->_idx]; | ||||||
3543 | LoopNode* new_head_clone = old_new[new_head->_idx]->as_Loop(); | ||||||
3544 | Node* orig_tail_clone = head_clone->in(2); | ||||||
3545 | |||||||
3546 | // Add phi if "def" node is in peel set and "use" is not | ||||||
3547 | |||||||
3548 | for (uint i = 0; i < peel_list.size(); i++) { | ||||||
3549 | Node *def = peel_list.at(i); | ||||||
3550 | if (!def->is_CFG()) { | ||||||
3551 | for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) { | ||||||
3552 | Node *use = def->fast_out(j); | ||||||
3553 | if (has_node(use) && use->in(0) != C->top() && | ||||||
3554 | (!peel.test(use->_idx) || | ||||||
3555 | (use->is_Phi() && use->in(0) == head)) ) { | ||||||
3556 | worklist.push(use); | ||||||
3557 | } | ||||||
3558 | } | ||||||
3559 | while( worklist.size() ) { | ||||||
3560 | Node *use = worklist.pop(); | ||||||
3561 | for (uint j = 1; j < use->req(); j++) { | ||||||
3562 | Node* n = use->in(j); | ||||||
3563 | if (n == def) { | ||||||
3564 | |||||||
3565 | // "def" is in peel set, "use" is not in peel set | ||||||
3566 | // or "use" is in the entry boundary (a phi) of the peel set | ||||||
3567 | |||||||
3568 | Node* use_c = has_ctrl(use) ? get_ctrl(use) : use; | ||||||
3569 | |||||||
3570 | if ( loop->is_member(get_loop( use_c )) ) { | ||||||
3571 | // use is in loop | ||||||
3572 | if (old_new[use->_idx] != NULL__null) { // null for dead code | ||||||
3573 | Node* use_clone = old_new[use->_idx]; | ||||||
3574 | _igvn.replace_input_of(use, j, C->top()); | ||||||
3575 | insert_phi_for_loop( use_clone, j, old_new[def->_idx], def, new_head_clone ); | ||||||
3576 | } | ||||||
3577 | } else { | ||||||
3578 | assert(is_valid_clone_loop_exit_use(loop, use, orig_exit_idx), "clone loop format")do { if (!(is_valid_clone_loop_exit_use(loop, use, orig_exit_idx ))) { (*g_assert_poison) = 'X';; report_vm_error("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3578, "assert(" "is_valid_clone_loop_exit_use(loop, use, orig_exit_idx)" ") failed", "clone loop format"); ::breakpoint(); } } while ( 0); | ||||||
3579 | // use is not in the loop, check if the live range includes the cut | ||||||
3580 | Node* lp_if = use_c->in(orig_exit_idx)->in(0); | ||||||
3581 | if (not_peel.test(lp_if->_idx)) { | ||||||
3582 | assert(j == orig_exit_idx, "use from original loop")do { if (!(j == orig_exit_idx)) { (*g_assert_poison) = 'X';; report_vm_error ("/home/daniel/Projects/java/jdk/src/hotspot/share/opto/loopopts.cpp" , 3582, "assert(" "j == orig_exit_idx" ") failed", "use from original loop" ); ::breakpoint(); } } while (0); | ||||||
3583 | insert_phi_for_loop( use, clone_exit_idx, old_new[def->_idx], def, new_head_clone ); | ||||||
3584 | } | ||||||
3585 | } | ||||||
3586 | } | ||||||
3587 | } | ||||||
3588 | } | ||||||
3589 | } | ||||||
3590 | } | ||||||
3591 | |||||||
3592 | // Step 3b: retarget control | ||||||
3593 | |||||||
3594 | // Redirect control to the new loop head if a cloned node in | ||||||
3595 | // the not_peeled region has control that points into the peeled region. | ||||||
3596 | // This necessary because the cloned peeled region will be outside | ||||||
3597 | // the loop. | ||||||
3598 | // from to | ||||||
3599 | // cloned-peeled <---+ | ||||||
3600 | // new_head_clone: | <--+ | ||||||
3601 | // cloned-not_peeled in(0) in(0) | ||||||
3602 | // orig-peeled | ||||||
3603 | |||||||
3604 | for (uint i = 0; i < loop->_body.size(); i++) { | ||||||
3605 | Node *n = loop->_body.at(i); | ||||||
3606 | if (!n->is_CFG() && n->in(0) != NULL__null && | ||||||
3607 | not_peel.test(n->_idx) && peel.test(n->in(0)->_idx)) { | ||||||
3608 | Node* n_clone = old_new[n->_idx]; | ||||||
3609 | _igvn.replace_input_of(n_clone, 0, new_head_clone); | ||||||
3610 | } | ||||||
3611 | } | ||||||
3612 | |||||||
3613 | // Backedge of the surviving new_head (the clone) is original last_peel | ||||||
3614 | _igvn.replace_input_of(new_head_clone, LoopNode::LoopBackControl, last_peel); | ||||||
3615 | |||||||
3616 | // Cut first node in original not_peel set | ||||||
3617 | _igvn.rehash_node_delayed(new_head); // Multiple edge updates: | ||||||
3618 | new_head->set_req(LoopNode::EntryControl, C->top()); // use rehash_node_delayed / set_req instead of | ||||||
3619 | new_head->set_req(LoopNode::LoopBackControl, C->top()); // multiple replace_input_of calls | ||||||
3620 | |||||||
3621 | // Copy head_clone back-branch info to original head | ||||||
3622 | // and remove original head's loop entry and | ||||||
3623 | // clone head's back-branch | ||||||
3624 | _igvn.rehash_node_delayed(head); // Multiple edge updates | ||||||
3625 | head->set_req(LoopNode::EntryControl, head_clone->in(LoopNode::LoopBackControl)); | ||||||
3626 | head->set_req(LoopNode::LoopBackControl, C->top()); | ||||||
3627 | _igvn.replace_input_of(head_clone, LoopNode::LoopBackControl, C->top()); | ||||||
3628 | |||||||
3629 | // Similarly modify the phis | ||||||
3630 | for (DUIterator_Fast kmax, k = head->fast_outs(kmax); k < kmax; k++) { | ||||||
3631 | Node* use = head->fast_out(k); | ||||||
3632 | if (use->is_Phi() && use->outcnt() > 0) { | ||||||
3633 | Node* use_clone = old_new[use->_idx]; | ||||||
3634 | _igvn.rehash_node_delayed(use); // Multiple edge updates | ||||||
3635 | use->set_req(LoopNode::EntryControl, use_clone->in(LoopNode::LoopBackControl)); | ||||||
3636 | use->set_req(LoopNode::LoopBackControl, C->top()); | ||||||
3637 | _igvn.replace_input_of(use_clone, LoopNode::LoopBackControl, C->top()); | ||||||
3638 | } | ||||||
3639 | } | ||||||
3640 | |||||||
3641 | // Step 4: update dominator tree and dominator depth | ||||||
3642 | |||||||
3643 | set_idom(head, orig_tail_clone, dd); | ||||||
3644 | recompute_dom_depth(); | ||||||
3645 | |||||||
3646 | // Inhibit more partial peeling on this loop | ||||||
3647 | new_head_clone->set_partial_peel_loop(); | ||||||
3648 | C->set_major_progress(); | ||||||
3649 | loop->record_for_igvn(); | ||||||
3650 | |||||||
3651 | #ifndef PRODUCT | ||||||
3652 | if (TracePartialPeeling) { | ||||||
3653 | tty->print_cr("\nafter partial peel one iteration"); | ||||||
3654 | Node_List wl; | ||||||
3655 | Node* t = last_peel; | ||||||
3656 | while (true) { | ||||||
3657 | wl.push(t); | ||||||
3658 | if (t == head_clone) break; | ||||||
3659 | t = idom(t); | ||||||
3660 | } | ||||||
3661 | while (wl.size() > 0) { | ||||||
3662 | Node* tt = wl.pop(); | ||||||
3663 | if (tt == head) tty->print_cr("orig head"); | ||||||
3664 | else if (tt == new_head_clone) tty->print_cr("new head"); | ||||||
3665 | else if (tt == head_clone) tty->print_cr("clone head"); | ||||||
3666 | tt->dump(); | ||||||
3667 | } | ||||||
3668 | } | ||||||
3669 | #endif | ||||||
3670 | return true; | ||||||
3671 | } | ||||||
3672 | |||||||
3673 | //------------------------------reorg_offsets---------------------------------- | ||||||
3674 | // Reorganize offset computations to lower register pressure. Mostly | ||||||
3675 | // prevent loop-fallout uses of the pre-incremented trip counter (which are | ||||||
3676 | // then alive with the post-incremented trip counter forcing an extra | ||||||
3677 | // register move) | ||||||
3678 | void PhaseIdealLoop::reorg_offsets(IdealLoopTree *loop) { | ||||||
3679 | // Perform it only for canonical counted loops. | ||||||
3680 | // Loop's shape could be messed up by iteration_split_impl. | ||||||
3681 | if (!loop->_head->is_CountedLoop()) | ||||||
3682 | return; | ||||||
3683 | if (!loop->_head->as_Loop()->is_valid_counted_loop(T_INT)) | ||||||
3684 | return; | ||||||
3685 | |||||||
3686 | CountedLoopNode *cl = loop->_head->as_CountedLoop(); | ||||||
3687 | CountedLoopEndNode *cle = cl->loopexit(); | ||||||
3688 | Node *exit = cle->proj_out(false); | ||||||
3689 | Node *phi = cl->phi(); | ||||||
3690 | |||||||
3691 | // Check for the special case when using the pre-incremented trip-counter on | ||||||
3692 | // the fall-out path (forces the pre-incremented and post-incremented trip | ||||||
3693 | // counter to be live at the same time). Fix this by adjusting to use the | ||||||
3694 | // post-increment trip counter. | ||||||
3695 | |||||||
3696 | bool progress = true; | ||||||
3697 | while (progress) { | ||||||
3698 | progress = false; | ||||||
3699 | for (DUIterator_Fast imax, i = phi->fast_outs(imax); i < imax; i++) { | ||||||
3700 | Node* use = phi->fast_out(i); // User of trip-counter | ||||||
3701 | if (!has_ctrl(use)) continue; | ||||||
3702 | Node *u_ctrl = get_ctrl(use); | ||||||
3703 | if (use->is_Phi()) { | ||||||
3704 | u_ctrl = NULL__null; | ||||||
3705 | for (uint j = 1; j < use->req(); j++) | ||||||
3706 | if (use->in(j) == phi) | ||||||
3707 | u_ctrl = dom_lca(u_ctrl, use->in(0)->in(j)); | ||||||
3708 | } | ||||||
3709 | IdealLoopTree *u_loop = get_loop(u_ctrl); | ||||||
3710 | // Look for loop-invariant use | ||||||
3711 | if (u_loop == loop) continue; | ||||||
3712 | if (loop->is_member(u_loop)) continue; | ||||||
3713 | // Check that use is live out the bottom. Assuming the trip-counter | ||||||
3714 | // update is right at the bottom, uses of of the loop middle are ok. | ||||||
3715 | if (dom_lca(exit, u_ctrl) != exit) continue; | ||||||
3716 | // Hit! Refactor use to use the post-incremented tripcounter. | ||||||
3717 | // Compute a post-increment tripcounter. | ||||||
3718 | Node* c = exit; | ||||||
3719 | if (cl->is_strip_mined()) { | ||||||
3720 | IdealLoopTree* outer_loop = get_loop(cl->outer_loop()); | ||||||
3721 | if (!outer_loop->is_member(u_loop)) { | ||||||
3722 | c = cl->outer_loop_exit(); | ||||||
3723 | } | ||||||
3724 | } | ||||||
3725 | Node *opaq = new Opaque2Node(C, cle->incr()); | ||||||
3726 | register_new_node(opaq, c); | ||||||
3727 | Node *neg_stride = _igvn.intcon(-cle->stride_con()); | ||||||
3728 | set_ctrl(neg_stride, C->root()); | ||||||
3729 | Node *post = new AddINode(opaq, neg_stride); | ||||||
3730 | register_new_node(post, c); | ||||||
3731 | _igvn.rehash_node_delayed(use); | ||||||
3732 | for (uint j = 1; j < use->req(); j++) { | ||||||
3733 | if (use->in(j) == phi) | ||||||
3734 | use->set_req(j, post); | ||||||
3735 | } | ||||||
3736 | // Since DU info changed, rerun loop | ||||||
3737 | progress = true; | ||||||
3738 | break; | ||||||
3739 | } | ||||||
3740 | } | ||||||
3741 | |||||||
3742 | } |
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 |