Mercurial > hg > truffle
annotate src/share/vm/opto/loopPredicate.cpp @ 17716:cdb71841f4bc
6498581: ThreadInterruptTest3 produces wrong output on Windows
Summary: There is race condition between os::interrupt and os::is_interrupted on Windows. In JVM_Sleep(Thread.sleep), check if thread gets interrupted, it may see interrupted but not really interrupted so cause spurious waking up (early return from sleep). Fix by checking if interrupt event really gets set thus prevent false return. For intrinsic of _isInterrupted, on Windows, go fastpath only on bit not set.
Reviewed-by: acorn, kvn
Contributed-by: david.holmes@oracle.com, yumin.qi@oracle.com
author | minqi |
---|---|
date | Wed, 26 Feb 2014 15:20:41 -0800 |
parents | 55fb97c4c58d |
children | 4ca6dc0799b6 78bbf4d43a14 |
rev | line source |
---|---|
2445 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
12956
diff
changeset
|
2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. |
2445 | 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 "opto/loopnode.hpp" | |
27 #include "opto/addnode.hpp" | |
28 #include "opto/callnode.hpp" | |
29 #include "opto/connode.hpp" | |
30 #include "opto/loopnode.hpp" | |
31 #include "opto/mulnode.hpp" | |
32 #include "opto/rootnode.hpp" | |
33 #include "opto/subnode.hpp" | |
34 | |
35 /* | |
36 * The general idea of Loop Predication is to insert a predicate on the entry | |
37 * path to a loop, and raise a uncommon trap if the check of the condition fails. | |
38 * The condition checks are promoted from inside the loop body, and thus | |
39 * the checks inside the loop could be eliminated. Currently, loop predication | |
40 * optimization has been applied to remove array range check and loop invariant | |
41 * checks (such as null checks). | |
42 */ | |
43 | |
44 //-------------------------------register_control------------------------- | |
45 void PhaseIdealLoop::register_control(Node* n, IdealLoopTree *loop, Node* pred) { | |
46 assert(n->is_CFG(), "must be control node"); | |
47 _igvn.register_new_node_with_optimizer(n); | |
48 loop->_body.push(n); | |
49 set_loop(n, loop); | |
50 // When called from beautify_loops() idom is not constructed yet. | |
51 if (_idom != NULL) { | |
52 set_idom(n, pred, dom_depth(pred)); | |
53 } | |
54 } | |
55 | |
56 //------------------------------create_new_if_for_predicate------------------------ | |
57 // create a new if above the uct_if_pattern for the predicate to be promoted. | |
58 // | |
59 // before after | |
60 // ---------- ---------- | |
61 // ctrl ctrl | |
62 // | | | |
63 // | | | |
64 // v v | |
65 // iff new_iff | |
66 // / \ / \ | |
67 // / \ / \ | |
68 // v v v v | |
69 // uncommon_proj cont_proj if_uct if_cont | |
70 // \ | | | | | |
71 // \ | | | | | |
72 // v v v | v | |
73 // rgn loop | iff | |
74 // | | / \ | |
75 // | | / \ | |
76 // v | v v | |
77 // uncommon_trap | uncommon_proj cont_proj | |
78 // \ \ | | | |
79 // \ \ | | | |
80 // v v v v | |
81 // rgn loop | |
82 // | | |
83 // | | |
84 // v | |
85 // uncommon_trap | |
86 // | |
87 // | |
88 // We will create a region to guard the uct call if there is no one there. | |
89 // The true projecttion (if_cont) of the new_iff is returned. | |
90 // This code is also used to clone predicates to clonned loops. | |
91 ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry, | |
92 Deoptimization::DeoptReason reason) { | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
93 assert(cont_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!"); |
2445 | 94 IfNode* iff = cont_proj->in(0)->as_If(); |
95 | |
96 ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con); | |
97 Node *rgn = uncommon_proj->unique_ctrl_out(); | |
98 assert(rgn->is_Region() || rgn->is_Call(), "must be a region or call uct"); | |
99 | |
100 uint proj_index = 1; // region's edge corresponding to uncommon_proj | |
101 if (!rgn->is_Region()) { // create a region to guard the call | |
102 assert(rgn->is_Call(), "must be call uct"); | |
103 CallNode* call = rgn->as_Call(); | |
104 IdealLoopTree* loop = get_loop(call); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
105 rgn = new (C) RegionNode(1); |
2445 | 106 rgn->add_req(uncommon_proj); |
107 register_control(rgn, loop, uncommon_proj); | |
108 _igvn.hash_delete(call); | |
109 call->set_req(0, rgn); | |
110 // When called from beautify_loops() idom is not constructed yet. | |
111 if (_idom != NULL) { | |
112 set_idom(call, rgn, dom_depth(rgn)); | |
113 } | |
114 } else { | |
115 // Find region's edge corresponding to uncommon_proj | |
116 for (; proj_index < rgn->req(); proj_index++) | |
117 if (rgn->in(proj_index) == uncommon_proj) break; | |
118 assert(proj_index < rgn->req(), "sanity"); | |
119 } | |
120 | |
121 Node* entry = iff->in(0); | |
122 if (new_entry != NULL) { | |
123 // Clonning the predicate to new location. | |
124 entry = new_entry; | |
125 } | |
126 // Create new_iff | |
127 IdealLoopTree* lp = get_loop(entry); | |
128 IfNode *new_iff = iff->clone()->as_If(); | |
129 new_iff->set_req(0, entry); | |
130 register_control(new_iff, lp, entry); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
131 Node *if_cont = new (C) IfTrueNode(new_iff); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
132 Node *if_uct = new (C) IfFalseNode(new_iff); |
2445 | 133 if (cont_proj->is_IfFalse()) { |
134 // Swap | |
135 Node* tmp = if_uct; if_uct = if_cont; if_cont = tmp; | |
136 } | |
137 register_control(if_cont, lp, new_iff); | |
138 register_control(if_uct, get_loop(rgn), new_iff); | |
139 | |
140 // if_uct to rgn | |
141 _igvn.hash_delete(rgn); | |
142 rgn->add_req(if_uct); | |
143 // When called from beautify_loops() idom is not constructed yet. | |
144 if (_idom != NULL) { | |
145 Node* ridom = idom(rgn); | |
146 Node* nrdom = dom_lca(ridom, new_iff); | |
147 set_idom(rgn, nrdom, dom_depth(rgn)); | |
148 } | |
149 | |
150 // If rgn has phis add new edges which has the same | |
151 // value as on original uncommon_proj pass. | |
152 assert(rgn->in(rgn->req() -1) == if_uct, "new edge should be last"); | |
153 bool has_phi = false; | |
154 for (DUIterator_Fast imax, i = rgn->fast_outs(imax); i < imax; i++) { | |
155 Node* use = rgn->fast_out(i); | |
156 if (use->is_Phi() && use->outcnt() > 0) { | |
157 assert(use->in(0) == rgn, ""); | |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3850
diff
changeset
|
158 _igvn.rehash_node_delayed(use); |
2445 | 159 use->add_req(use->in(proj_index)); |
160 has_phi = true; | |
161 } | |
162 } | |
163 assert(!has_phi || rgn->req() > 3, "no phis when region is created"); | |
164 | |
165 if (new_entry == NULL) { | |
166 // Attach if_cont to iff | |
167 _igvn.hash_delete(iff); | |
168 iff->set_req(0, if_cont); | |
169 if (_idom != NULL) { | |
170 set_idom(iff, if_cont, dom_depth(iff)); | |
171 } | |
172 } | |
173 return if_cont->as_Proj(); | |
174 } | |
175 | |
176 //------------------------------create_new_if_for_predicate------------------------ | |
177 // Create a new if below new_entry for the predicate to be cloned (IGVN optimization) | |
178 ProjNode* PhaseIterGVN::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry, | |
179 Deoptimization::DeoptReason reason) { | |
180 assert(new_entry != 0, "only used for clone predicate"); | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
181 assert(cont_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!"); |
2445 | 182 IfNode* iff = cont_proj->in(0)->as_If(); |
183 | |
184 ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con); | |
185 Node *rgn = uncommon_proj->unique_ctrl_out(); | |
186 assert(rgn->is_Region() || rgn->is_Call(), "must be a region or call uct"); | |
187 | |
188 uint proj_index = 1; // region's edge corresponding to uncommon_proj | |
189 if (!rgn->is_Region()) { // create a region to guard the call | |
190 assert(rgn->is_Call(), "must be call uct"); | |
191 CallNode* call = rgn->as_Call(); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
192 rgn = new (C) RegionNode(1); |
2445 | 193 register_new_node_with_optimizer(rgn); |
194 rgn->add_req(uncommon_proj); | |
195 hash_delete(call); | |
196 call->set_req(0, rgn); | |
197 } else { | |
198 // Find region's edge corresponding to uncommon_proj | |
199 for (; proj_index < rgn->req(); proj_index++) | |
200 if (rgn->in(proj_index) == uncommon_proj) break; | |
201 assert(proj_index < rgn->req(), "sanity"); | |
202 } | |
203 | |
204 // Create new_iff in new location. | |
205 IfNode *new_iff = iff->clone()->as_If(); | |
206 new_iff->set_req(0, new_entry); | |
207 | |
208 register_new_node_with_optimizer(new_iff); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
209 Node *if_cont = new (C) IfTrueNode(new_iff); |
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
210 Node *if_uct = new (C) IfFalseNode(new_iff); |
2445 | 211 if (cont_proj->is_IfFalse()) { |
212 // Swap | |
213 Node* tmp = if_uct; if_uct = if_cont; if_cont = tmp; | |
214 } | |
215 register_new_node_with_optimizer(if_cont); | |
216 register_new_node_with_optimizer(if_uct); | |
217 | |
218 // if_uct to rgn | |
219 hash_delete(rgn); | |
220 rgn->add_req(if_uct); | |
221 | |
222 // If rgn has phis add corresponding new edges which has the same | |
223 // value as on original uncommon_proj pass. | |
224 assert(rgn->in(rgn->req() -1) == if_uct, "new edge should be last"); | |
225 bool has_phi = false; | |
226 for (DUIterator_Fast imax, i = rgn->fast_outs(imax); i < imax; i++) { | |
227 Node* use = rgn->fast_out(i); | |
228 if (use->is_Phi() && use->outcnt() > 0) { | |
6144
5e990493719e
7173340: C2: code cleanup: use PhaseIterGVN::replace_edge(Node*, int, Node*) where applicable
kvn
parents:
3850
diff
changeset
|
229 rehash_node_delayed(use); |
2445 | 230 use->add_req(use->in(proj_index)); |
231 has_phi = true; | |
232 } | |
233 } | |
234 assert(!has_phi || rgn->req() > 3, "no phis when region is created"); | |
235 | |
236 return if_cont->as_Proj(); | |
237 } | |
238 | |
239 //--------------------------clone_predicate----------------------- | |
240 ProjNode* PhaseIdealLoop::clone_predicate(ProjNode* predicate_proj, Node* new_entry, | |
241 Deoptimization::DeoptReason reason, | |
242 PhaseIdealLoop* loop_phase, | |
243 PhaseIterGVN* igvn) { | |
244 ProjNode* new_predicate_proj; | |
245 if (loop_phase != NULL) { | |
246 new_predicate_proj = loop_phase->create_new_if_for_predicate(predicate_proj, new_entry, reason); | |
247 } else { | |
248 new_predicate_proj = igvn->create_new_if_for_predicate(predicate_proj, new_entry, reason); | |
249 } | |
250 IfNode* iff = new_predicate_proj->in(0)->as_If(); | |
251 Node* ctrl = iff->in(0); | |
252 | |
253 // Match original condition since predicate's projections could be swapped. | |
254 assert(predicate_proj->in(0)->in(1)->in(1)->Opcode()==Op_Opaque1, "must be"); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
255 Node* opq = new (igvn->C) Opaque1Node(igvn->C, predicate_proj->in(0)->in(1)->in(1)->in(1)); |
2445 | 256 igvn->C->add_predicate_opaq(opq); |
257 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
258 Node* bol = new (igvn->C) Conv2BNode(opq); |
2445 | 259 if (loop_phase != NULL) { |
260 loop_phase->register_new_node(opq, ctrl); | |
261 loop_phase->register_new_node(bol, ctrl); | |
262 } else { | |
263 igvn->register_new_node_with_optimizer(opq); | |
264 igvn->register_new_node_with_optimizer(bol); | |
265 } | |
266 igvn->hash_delete(iff); | |
267 iff->set_req(1, bol); | |
268 return new_predicate_proj; | |
269 } | |
270 | |
271 | |
272 //--------------------------clone_loop_predicates----------------------- | |
273 // Interface from IGVN | |
3345 | 274 Node* PhaseIterGVN::clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) { |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
275 return PhaseIdealLoop::clone_loop_predicates(old_entry, new_entry, clone_limit_check, NULL, this); |
2445 | 276 } |
277 | |
278 // Interface from PhaseIdealLoop | |
3345 | 279 Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry, bool clone_limit_check) { |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
280 return clone_loop_predicates(old_entry, new_entry, clone_limit_check, this, &this->_igvn); |
2445 | 281 } |
282 | |
283 // Clone loop predicates to cloned loops (peeled, unswitched, split_if). | |
284 Node* PhaseIdealLoop::clone_loop_predicates(Node* old_entry, Node* new_entry, | |
3345 | 285 bool clone_limit_check, |
2445 | 286 PhaseIdealLoop* loop_phase, |
287 PhaseIterGVN* igvn) { | |
288 #ifdef ASSERT | |
289 if (new_entry == NULL || !(new_entry->is_Proj() || new_entry->is_Region() || new_entry->is_SafePoint())) { | |
290 if (new_entry != NULL) | |
291 new_entry->dump(); | |
292 assert(false, "not IfTrue, IfFalse, Region or SafePoint"); | |
293 } | |
294 #endif | |
295 // Search original predicates | |
296 Node* entry = old_entry; | |
3345 | 297 ProjNode* limit_check_proj = NULL; |
298 if (LoopLimitCheck) { | |
299 limit_check_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); | |
300 if (limit_check_proj != NULL) { | |
301 entry = entry->in(0)->in(0); | |
302 } | |
303 } | |
2445 | 304 if (UseLoopPredicate) { |
305 ProjNode* predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); | |
306 if (predicate_proj != NULL) { // right pattern that can be used by loop predication | |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
307 // clone predicate |
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
308 new_entry = clone_predicate(predicate_proj, new_entry, |
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
309 Deoptimization::Reason_predicate, |
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
310 loop_phase, igvn); |
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
311 assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone predicate"); |
2445 | 312 if (TraceLoopPredicate) { |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
313 tty->print("Loop Predicate cloned: "); |
2445 | 314 debug_only( new_entry->in(0)->dump(); ) |
315 } | |
316 } | |
317 } | |
3345 | 318 if (limit_check_proj != NULL && clone_limit_check) { |
319 // Clone loop limit check last to insert it before loop. | |
320 // Don't clone a limit check which was already finalized | |
321 // for this counted loop (only one limit check is needed). | |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
322 new_entry = clone_predicate(limit_check_proj, new_entry, |
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
323 Deoptimization::Reason_loop_limit_check, |
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
324 loop_phase, igvn); |
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
325 assert(new_entry != NULL && new_entry->is_Proj(), "IfTrue or IfFalse after clone limit check"); |
3345 | 326 if (TraceLoopLimitCheck) { |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3840
diff
changeset
|
327 tty->print("Loop Limit Check cloned: "); |
3345 | 328 debug_only( new_entry->in(0)->dump(); ) |
329 } | |
330 } | |
2445 | 331 return new_entry; |
332 } | |
333 | |
334 //--------------------------skip_loop_predicates------------------------------ | |
335 // Skip related predicates. | |
336 Node* PhaseIdealLoop::skip_loop_predicates(Node* entry) { | |
337 Node* predicate = NULL; | |
3345 | 338 if (LoopLimitCheck) { |
339 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); | |
340 if (predicate != NULL) { | |
341 entry = entry->in(0)->in(0); | |
342 } | |
343 } | |
2445 | 344 if (UseLoopPredicate) { |
345 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); | |
346 if (predicate != NULL) { // right pattern that can be used by loop predication | |
347 IfNode* iff = entry->in(0)->as_If(); | |
348 ProjNode* uncommon_proj = iff->proj_out(1 - entry->as_Proj()->_con); | |
349 Node* rgn = uncommon_proj->unique_ctrl_out(); | |
350 assert(rgn->is_Region() || rgn->is_Call(), "must be a region or call uct"); | |
351 entry = entry->in(0)->in(0); | |
352 while (entry != NULL && entry->is_Proj() && entry->in(0)->is_If()) { | |
353 uncommon_proj = entry->in(0)->as_If()->proj_out(1 - entry->as_Proj()->_con); | |
354 if (uncommon_proj->unique_ctrl_out() != rgn) | |
355 break; | |
356 entry = entry->in(0)->in(0); | |
357 } | |
358 } | |
359 } | |
360 return entry; | |
361 } | |
362 | |
363 //--------------------------find_predicate_insertion_point------------------- | |
364 // Find a good location to insert a predicate | |
365 ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c, Deoptimization::DeoptReason reason) { | |
366 if (start_c == NULL || !start_c->is_Proj()) | |
367 return NULL; | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
368 if (start_c->as_Proj()->is_uncommon_trap_if_pattern(reason)) { |
2445 | 369 return start_c->as_Proj(); |
370 } | |
371 return NULL; | |
372 } | |
373 | |
374 //--------------------------find_predicate------------------------------------ | |
375 // Find a predicate | |
376 Node* PhaseIdealLoop::find_predicate(Node* entry) { | |
377 Node* predicate = NULL; | |
3345 | 378 if (LoopLimitCheck) { |
379 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); | |
380 if (predicate != NULL) { // right pattern that can be used by loop predication | |
381 return entry; | |
382 } | |
383 } | |
2445 | 384 if (UseLoopPredicate) { |
385 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); | |
386 if (predicate != NULL) { // right pattern that can be used by loop predication | |
387 return entry; | |
388 } | |
389 } | |
390 return NULL; | |
391 } | |
392 | |
393 //------------------------------Invariance----------------------------------- | |
394 // Helper class for loop_predication_impl to compute invariance on the fly and | |
395 // clone invariants. | |
396 class Invariance : public StackObj { | |
397 VectorSet _visited, _invariant; | |
398 Node_Stack _stack; | |
399 VectorSet _clone_visited; | |
400 Node_List _old_new; // map of old to new (clone) | |
401 IdealLoopTree* _lpt; | |
402 PhaseIdealLoop* _phase; | |
403 | |
404 // Helper function to set up the invariance for invariance computation | |
405 // If n is a known invariant, set up directly. Otherwise, look up the | |
406 // the possibility to push n onto the stack for further processing. | |
407 void visit(Node* use, Node* n) { | |
408 if (_lpt->is_invariant(n)) { // known invariant | |
409 _invariant.set(n->_idx); | |
410 } else if (!n->is_CFG()) { | |
411 Node *n_ctrl = _phase->ctrl_or_self(n); | |
412 Node *u_ctrl = _phase->ctrl_or_self(use); // self if use is a CFG | |
413 if (_phase->is_dominator(n_ctrl, u_ctrl)) { | |
414 _stack.push(n, n->in(0) == NULL ? 1 : 0); | |
415 } | |
416 } | |
417 } | |
418 | |
419 // Compute invariance for "the_node" and (possibly) all its inputs recursively | |
420 // on the fly | |
421 void compute_invariance(Node* n) { | |
422 assert(_visited.test(n->_idx), "must be"); | |
423 visit(n, n); | |
424 while (_stack.is_nonempty()) { | |
425 Node* n = _stack.node(); | |
426 uint idx = _stack.index(); | |
427 if (idx == n->req()) { // all inputs are processed | |
428 _stack.pop(); | |
429 // n is invariant if it's inputs are all invariant | |
430 bool all_inputs_invariant = true; | |
431 for (uint i = 0; i < n->req(); i++) { | |
432 Node* in = n->in(i); | |
433 if (in == NULL) continue; | |
434 assert(_visited.test(in->_idx), "must have visited input"); | |
435 if (!_invariant.test(in->_idx)) { // bad guy | |
436 all_inputs_invariant = false; | |
437 break; | |
438 } | |
439 } | |
440 if (all_inputs_invariant) { | |
441 _invariant.set(n->_idx); // I am a invariant too | |
442 } | |
443 } else { // process next input | |
444 _stack.set_index(idx + 1); | |
445 Node* m = n->in(idx); | |
446 if (m != NULL && !_visited.test_set(m->_idx)) { | |
447 visit(n, m); | |
448 } | |
449 } | |
450 } | |
451 } | |
452 | |
453 // Helper function to set up _old_new map for clone_nodes. | |
454 // If n is a known invariant, set up directly ("clone" of n == n). | |
455 // Otherwise, push n onto the stack for real cloning. | |
456 void clone_visit(Node* n) { | |
457 assert(_invariant.test(n->_idx), "must be invariant"); | |
458 if (_lpt->is_invariant(n)) { // known invariant | |
459 _old_new.map(n->_idx, n); | |
460 } else { // to be cloned | |
461 assert(!n->is_CFG(), "should not see CFG here"); | |
462 _stack.push(n, n->in(0) == NULL ? 1 : 0); | |
463 } | |
464 } | |
465 | |
466 // Clone "n" and (possibly) all its inputs recursively | |
467 void clone_nodes(Node* n, Node* ctrl) { | |
468 clone_visit(n); | |
469 while (_stack.is_nonempty()) { | |
470 Node* n = _stack.node(); | |
471 uint idx = _stack.index(); | |
472 if (idx == n->req()) { // all inputs processed, clone n! | |
473 _stack.pop(); | |
474 // clone invariant node | |
475 Node* n_cl = n->clone(); | |
476 _old_new.map(n->_idx, n_cl); | |
477 _phase->register_new_node(n_cl, ctrl); | |
478 for (uint i = 0; i < n->req(); i++) { | |
479 Node* in = n_cl->in(i); | |
480 if (in == NULL) continue; | |
481 n_cl->set_req(i, _old_new[in->_idx]); | |
482 } | |
483 } else { // process next input | |
484 _stack.set_index(idx + 1); | |
485 Node* m = n->in(idx); | |
486 if (m != NULL && !_clone_visited.test_set(m->_idx)) { | |
487 clone_visit(m); // visit the input | |
488 } | |
489 } | |
490 } | |
491 } | |
492 | |
493 public: | |
494 Invariance(Arena* area, IdealLoopTree* lpt) : | |
495 _lpt(lpt), _phase(lpt->_phase), | |
496 _visited(area), _invariant(area), _stack(area, 10 /* guess */), | |
497 _clone_visited(area), _old_new(area) | |
498 {} | |
499 | |
500 // Map old to n for invariance computation and clone | |
501 void map_ctrl(Node* old, Node* n) { | |
502 assert(old->is_CFG() && n->is_CFG(), "must be"); | |
503 _old_new.map(old->_idx, n); // "clone" of old is n | |
504 _invariant.set(old->_idx); // old is invariant | |
505 _clone_visited.set(old->_idx); | |
506 } | |
507 | |
508 // Driver function to compute invariance | |
509 bool is_invariant(Node* n) { | |
510 if (!_visited.test_set(n->_idx)) | |
511 compute_invariance(n); | |
512 return (_invariant.test(n->_idx) != 0); | |
513 } | |
514 | |
515 // Driver function to clone invariant | |
516 Node* clone(Node* n, Node* ctrl) { | |
517 assert(ctrl->is_CFG(), "must be"); | |
518 assert(_invariant.test(n->_idx), "must be an invariant"); | |
519 if (!_clone_visited.test(n->_idx)) | |
520 clone_nodes(n, ctrl); | |
521 return _old_new[n->_idx]; | |
522 } | |
523 }; | |
524 | |
525 //------------------------------is_range_check_if ----------------------------------- | |
526 // Returns true if the predicate of iff is in "scale*iv + offset u< load_range(ptr)" format | |
527 // Note: this function is particularly designed for loop predication. We require load_range | |
528 // and offset to be loop invariant computed on the fly by "invar" | |
529 bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const { | |
530 if (!is_loop_exit(iff)) { | |
531 return false; | |
532 } | |
533 if (!iff->in(1)->is_Bool()) { | |
534 return false; | |
535 } | |
536 const BoolNode *bol = iff->in(1)->as_Bool(); | |
537 if (bol->_test._test != BoolTest::lt) { | |
538 return false; | |
539 } | |
540 if (!bol->in(1)->is_Cmp()) { | |
541 return false; | |
542 } | |
543 const CmpNode *cmp = bol->in(1)->as_Cmp(); | |
544 if (cmp->Opcode() != Op_CmpU) { | |
545 return false; | |
546 } | |
547 Node* range = cmp->in(2); | |
548 if (range->Opcode() != Op_LoadRange) { | |
549 const TypeInt* tint = phase->_igvn.type(range)->isa_int(); | |
3345 | 550 if (tint == NULL || tint->empty() || tint->_lo < 0) { |
2445 | 551 // Allow predication on positive values that aren't LoadRanges. |
552 // This allows optimization of loops where the length of the | |
553 // array is a known value and doesn't need to be loaded back | |
554 // from the array. | |
555 return false; | |
556 } | |
557 } | |
558 if (!invar.is_invariant(range)) { | |
559 return false; | |
560 } | |
561 Node *iv = _head->as_CountedLoop()->phi(); | |
562 int scale = 0; | |
563 Node *offset = NULL; | |
564 if (!phase->is_scaled_iv_plus_offset(cmp->in(1), iv, &scale, &offset)) { | |
565 return false; | |
566 } | |
567 if (offset && !invar.is_invariant(offset)) { // offset must be invariant | |
568 return false; | |
569 } | |
570 return true; | |
571 } | |
572 | |
573 //------------------------------rc_predicate----------------------------------- | |
574 // Create a range check predicate | |
575 // | |
576 // for (i = init; i < limit; i += stride) { | |
577 // a[scale*i+offset] | |
578 // } | |
579 // | |
580 // Compute max(scale*i + offset) for init <= i < limit and build the predicate | |
581 // as "max(scale*i + offset) u< a.length". | |
582 // | |
583 // There are two cases for max(scale*i + offset): | |
584 // (1) stride*scale > 0 | |
585 // max(scale*i + offset) = scale*(limit-stride) + offset | |
586 // (2) stride*scale < 0 | |
587 // max(scale*i + offset) = scale*init + offset | |
3345 | 588 BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl, |
2445 | 589 int scale, Node* offset, |
590 Node* init, Node* limit, Node* stride, | |
591 Node* range, bool upper) { | |
3336
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
592 stringStream* predString = NULL; |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
593 if (TraceLoopPredicate) { |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
594 predString = new stringStream(); |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
595 predString->print("rc_predicate "); |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
596 } |
2445 | 597 |
598 Node* max_idx_expr = init; | |
599 int stride_con = stride->get_int(); | |
600 if ((stride_con > 0) == (scale > 0) == upper) { | |
3345 | 601 if (LoopLimitCheck) { |
602 // With LoopLimitCheck limit is not exact. | |
603 // Calculate exact limit here. | |
604 // Note, counted loop's test is '<' or '>'. | |
605 limit = exact_limit(loop); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
606 max_idx_expr = new (C) SubINode(limit, stride); |
3345 | 607 register_new_node(max_idx_expr, ctrl); |
608 if (TraceLoopPredicate) predString->print("(limit - stride) "); | |
609 } else { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
610 max_idx_expr = new (C) SubINode(limit, stride); |
3345 | 611 register_new_node(max_idx_expr, ctrl); |
612 if (TraceLoopPredicate) predString->print("(limit - stride) "); | |
613 } | |
2445 | 614 } else { |
3336
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
615 if (TraceLoopPredicate) predString->print("init "); |
2445 | 616 } |
617 | |
618 if (scale != 1) { | |
619 ConNode* con_scale = _igvn.intcon(scale); | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
620 max_idx_expr = new (C) MulINode(max_idx_expr, con_scale); |
2445 | 621 register_new_node(max_idx_expr, ctrl); |
3336
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
622 if (TraceLoopPredicate) predString->print("* %d ", scale); |
2445 | 623 } |
624 | |
625 if (offset && (!offset->is_Con() || offset->get_int() != 0)){ | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
626 max_idx_expr = new (C) AddINode(max_idx_expr, offset); |
2445 | 627 register_new_node(max_idx_expr, ctrl); |
628 if (TraceLoopPredicate) | |
3336
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
629 if (offset->is_Con()) predString->print("+ %d ", offset->get_int()); |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
630 else predString->print("+ offset "); |
2445 | 631 } |
632 | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
633 CmpUNode* cmp = new (C) CmpUNode(max_idx_expr, range); |
2445 | 634 register_new_node(cmp, ctrl); |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
635 BoolNode* bol = new (C) BoolNode(cmp, BoolTest::lt); |
2445 | 636 register_new_node(bol, ctrl); |
637 | |
3336
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
638 if (TraceLoopPredicate) { |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
639 predString->print_cr("<u range"); |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
640 tty->print(predString->as_string()); |
2e038ad0c1d0
7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents:
2445
diff
changeset
|
641 } |
2445 | 642 return bol; |
643 } | |
644 | |
645 //------------------------------ loop_predication_impl-------------------------- | |
646 // Insert loop predicates for null checks and range checks | |
647 bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { | |
648 if (!UseLoopPredicate) return false; | |
649 | |
650 if (!loop->_head->is_Loop()) { | |
651 // Could be a simple region when irreducible loops are present. | |
652 return false; | |
653 } | |
3345 | 654 LoopNode* head = loop->_head->as_Loop(); |
2445 | 655 |
3345 | 656 if (head->unique_ctrl_out()->Opcode() == Op_NeverBranch) { |
2445 | 657 // do nothing for infinite loops |
658 return false; | |
659 } | |
660 | |
661 CountedLoopNode *cl = NULL; | |
3850
6987871cfb9b
7077439: Possible reference through NULL in loopPredicate.cpp:726
kvn
parents:
3845
diff
changeset
|
662 if (head->is_valid_counted_loop()) { |
3345 | 663 cl = head->as_CountedLoop(); |
2445 | 664 // do nothing for iteration-splitted loops |
665 if (!cl->is_normal_loop()) return false; | |
3840
4e761e7e6e12
7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents:
3345
diff
changeset
|
666 // Avoid RCE if Counted loop's test is '!='. |
4e761e7e6e12
7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents:
3345
diff
changeset
|
667 BoolTest::mask bt = cl->loopexit()->test_trip(); |
4e761e7e6e12
7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents:
3345
diff
changeset
|
668 if (bt != BoolTest::lt && bt != BoolTest::gt) |
4e761e7e6e12
7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents:
3345
diff
changeset
|
669 cl = NULL; |
2445 | 670 } |
671 | |
3345 | 672 Node* entry = head->in(LoopNode::EntryControl); |
673 ProjNode *predicate_proj = NULL; | |
674 // Loop limit check predicate should be near the loop. | |
675 if (LoopLimitCheck) { | |
676 predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check); | |
677 if (predicate_proj != NULL) | |
678 entry = predicate_proj->in(0)->in(0); | |
679 } | |
2445 | 680 |
3345 | 681 predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate); |
2445 | 682 if (!predicate_proj) { |
683 #ifndef PRODUCT | |
684 if (TraceLoopPredicate) { | |
685 tty->print("missing predicate:"); | |
686 loop->dump_head(); | |
3345 | 687 head->dump(1); |
2445 | 688 } |
689 #endif | |
690 return false; | |
691 } | |
692 ConNode* zero = _igvn.intcon(0); | |
693 set_ctrl(zero, C->root()); | |
694 | |
695 ResourceArea *area = Thread::current()->resource_area(); | |
696 Invariance invar(area, loop); | |
697 | |
698 // Create list of if-projs such that a newer proj dominates all older | |
699 // projs in the list, and they all dominate loop->tail() | |
700 Node_List if_proj_list(area); | |
701 Node *current_proj = loop->tail(); //start from tail | |
702 while (current_proj != head) { | |
703 if (loop == get_loop(current_proj) && // still in the loop ? | |
704 current_proj->is_Proj() && // is a projection ? | |
705 current_proj->in(0)->Opcode() == Op_If) { // is a if projection ? | |
706 if_proj_list.push(current_proj); | |
707 } | |
708 current_proj = idom(current_proj); | |
709 } | |
710 | |
711 bool hoisted = false; // true if at least one proj is promoted | |
712 while (if_proj_list.size() > 0) { | |
713 // Following are changed to nonnull when a predicate can be hoisted | |
714 ProjNode* new_predicate_proj = NULL; | |
715 | |
716 ProjNode* proj = if_proj_list.pop()->as_Proj(); | |
717 IfNode* iff = proj->in(0)->as_If(); | |
718 | |
12956
3213ba4d3dff
8024069: replace_in_map() should operate on parent maps
roland
parents:
10278
diff
changeset
|
719 if (!proj->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) { |
2445 | 720 if (loop->is_loop_exit(iff)) { |
721 // stop processing the remaining projs in the list because the execution of them | |
722 // depends on the condition of "iff" (iff->in(1)). | |
723 break; | |
724 } else { | |
725 // Both arms are inside the loop. There are two cases: | |
726 // (1) there is one backward branch. In this case, any remaining proj | |
727 // in the if_proj list post-dominates "iff". So, the condition of "iff" | |
728 // does not determine the execution the remining projs directly, and we | |
729 // can safely continue. | |
730 // (2) both arms are forwarded, i.e. a diamond shape. In this case, "proj" | |
731 // does not dominate loop->tail(), so it can not be in the if_proj list. | |
732 continue; | |
733 } | |
734 } | |
735 | |
736 Node* test = iff->in(1); | |
737 if (!test->is_Bool()){ //Conv2B, ... | |
738 continue; | |
739 } | |
740 BoolNode* bol = test->as_Bool(); | |
741 if (invar.is_invariant(bol)) { | |
742 // Invariant test | |
743 new_predicate_proj = create_new_if_for_predicate(predicate_proj, NULL, | |
744 Deoptimization::Reason_predicate); | |
745 Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0); | |
746 BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool(); | |
747 | |
748 // Negate test if necessary | |
749 bool negated = false; | |
750 if (proj->_con != predicate_proj->_con) { | |
6804
e626685e9f6c
7193318: C2: remove number of inputs requirement from Node's new operator
kvn
parents:
6144
diff
changeset
|
751 new_predicate_bol = new (C) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate()); |
2445 | 752 register_new_node(new_predicate_bol, ctrl); |
753 negated = true; | |
754 } | |
755 IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If(); | |
756 _igvn.hash_delete(new_predicate_iff); | |
757 new_predicate_iff->set_req(1, new_predicate_bol); | |
758 #ifndef PRODUCT | |
759 if (TraceLoopPredicate) { | |
760 tty->print("Predicate invariant if%s: %d ", negated ? " negated" : "", new_predicate_iff->_idx); | |
761 loop->dump_head(); | |
762 } else if (TraceLoopOpts) { | |
763 tty->print("Predicate IC "); | |
764 loop->dump_head(); | |
765 } | |
766 #endif | |
10278 | 767 } else if ((cl != NULL) && (proj->_con == predicate_proj->_con) && |
768 loop->is_range_check_if(iff, this, invar)) { | |
2445 | 769 |
770 // Range check for counted loops | |
771 const Node* cmp = bol->in(1)->as_Cmp(); | |
772 Node* idx = cmp->in(1); | |
773 assert(!invar.is_invariant(idx), "index is variant"); | |
774 Node* rng = cmp->in(2); | |
3345 | 775 assert(rng->Opcode() == Op_LoadRange || _igvn.type(rng)->is_int() >= 0, "must be"); |
2445 | 776 assert(invar.is_invariant(rng), "range must be invariant"); |
777 int scale = 1; | |
778 Node* offset = zero; | |
779 bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset); | |
780 assert(ok, "must be index expression"); | |
781 | |
782 Node* init = cl->init_trip(); | |
783 Node* limit = cl->limit(); | |
784 Node* stride = cl->stride(); | |
785 | |
786 // Build if's for the upper and lower bound tests. The | |
787 // lower_bound test will dominate the upper bound test and all | |
788 // cloned or created nodes will use the lower bound test as | |
789 // their declared control. | |
790 ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate); | |
791 ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj, NULL, Deoptimization::Reason_predicate); | |
792 assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate"); | |
793 Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0); | |
794 | |
795 // Perform cloning to keep Invariance state correct since the | |
796 // late schedule will place invariant things in the loop. | |
797 rng = invar.clone(rng, ctrl); | |
798 if (offset && offset != zero) { | |
799 assert(invar.is_invariant(offset), "offset must be loop invariant"); | |
800 offset = invar.clone(offset, ctrl); | |
801 } | |
802 | |
803 // Test the lower bound | |
3345 | 804 Node* lower_bound_bol = rc_predicate(loop, ctrl, scale, offset, init, limit, stride, rng, false); |
2445 | 805 IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If(); |
806 _igvn.hash_delete(lower_bound_iff); | |
807 lower_bound_iff->set_req(1, lower_bound_bol); | |
808 if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx); | |
809 | |
810 // Test the upper bound | |
3840
4e761e7e6e12
7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents:
3345
diff
changeset
|
811 Node* upper_bound_bol = rc_predicate(loop, lower_bound_proj, scale, offset, init, limit, stride, rng, true); |
2445 | 812 IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If(); |
813 _igvn.hash_delete(upper_bound_iff); | |
814 upper_bound_iff->set_req(1, upper_bound_bol); | |
815 if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx); | |
816 | |
817 // Fall through into rest of the clean up code which will move | |
818 // any dependent nodes onto the upper bound test. | |
819 new_predicate_proj = upper_bound_proj; | |
820 | |
821 #ifndef PRODUCT | |
822 if (TraceLoopOpts && !TraceLoopPredicate) { | |
823 tty->print("Predicate RC "); | |
824 loop->dump_head(); | |
825 } | |
826 #endif | |
827 } else { | |
828 // Loop variant check (for example, range check in non-counted loop) | |
829 // with uncommon trap. | |
830 continue; | |
831 } | |
832 assert(new_predicate_proj != NULL, "sanity"); | |
833 // Success - attach condition (new_predicate_bol) to predicate if | |
834 invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate | |
835 | |
836 // Eliminate the old If in the loop body | |
837 dominated_by( new_predicate_proj, iff, proj->_con != new_predicate_proj->_con ); | |
838 | |
839 hoisted = true; | |
840 C->set_major_progress(); | |
841 } // end while | |
842 | |
843 #ifndef PRODUCT | |
844 // report that the loop predication has been actually performed | |
845 // for this loop | |
846 if (TraceLoopPredicate && hoisted) { | |
847 tty->print("Loop Predication Performed:"); | |
848 loop->dump_head(); | |
849 } | |
850 #endif | |
851 | |
852 return hoisted; | |
853 } | |
854 | |
855 //------------------------------loop_predication-------------------------------- | |
856 // driver routine for loop predication optimization | |
857 bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) { | |
858 bool hoisted = false; | |
859 // Recursively promote predicates | |
860 if (_child) { | |
861 hoisted = _child->loop_predication( phase); | |
862 } | |
863 | |
864 // self | |
865 if (!_irreducible && !tail()->is_top()) { | |
866 hoisted |= phase->loop_predication_impl(this); | |
867 } | |
868 | |
869 if (_next) { //sibling | |
870 hoisted |= _next->loop_predication( phase); | |
871 } | |
872 | |
873 return hoisted; | |
874 } |