Mercurial > hg > truffle
annotate src/share/vm/opto/loopUnswitch.cpp @ 4710:41406797186b
7113012: G1: rename not-fully-young GCs as "mixed"
Summary: Renamed partially-young GCs as mixed and fully-young GCs as young. Change all external output that includes those terms (GC log and GC ergo log) as well as any comments, fields, methods, etc. The changeset also includes very minor code tidying up (added some curly brackets).
Reviewed-by: johnc, brutisso
author | tonyp |
---|---|
date | Fri, 16 Dec 2011 02:14:27 -0500 |
parents | c96c3eb1efae |
children | 5e990493719e |
rev | line source |
---|---|
0 | 1 /* |
2426
1d1603768966
7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
trims
parents:
2383
diff
changeset
|
2 * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #include "precompiled.hpp" |
26 #include "memory/allocation.inline.hpp" | |
27 #include "opto/connode.hpp" | |
28 #include "opto/loopnode.hpp" | |
29 #include "opto/rootnode.hpp" | |
0 | 30 |
31 //================= Loop Unswitching ===================== | |
32 // | |
33 // orig: transformed: | |
34 // if (invariant-test) then | |
2445 | 35 // predicate predicate |
0 | 36 // loop loop |
37 // stmt1 stmt1 | |
38 // if (invariant-test) then stmt2 | |
39 // stmt2 stmt4 | |
40 // else endloop | |
41 // stmt3 else | |
2445 | 42 // endif predicate [clone] |
43 // stmt4 loop [clone] | |
44 // endloop stmt1 [clone] | |
45 // stmt3 | |
0 | 46 // stmt4 [clone] |
47 // endloop | |
48 // endif | |
49 // | |
50 // Note: the "else" clause may be empty | |
51 | |
52 //------------------------------policy_unswitching----------------------------- | |
53 // Return TRUE or FALSE if the loop should be unswitched | |
54 // (ie. clone loop with an invariant test that does not exit the loop) | |
55 bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { | |
56 if( !LoopUnswitching ) { | |
57 return false; | |
58 } | |
108 | 59 if (!_head->is_Loop()) { |
60 return false; | |
61 } | |
0 | 62 uint nodes_left = MaxNodeLimit - phase->C->unique(); |
63 if (2 * _body.size() > nodes_left) { | |
64 return false; // Too speculative if running low on nodes. | |
65 } | |
66 LoopNode* head = _head->as_Loop(); | |
67 if (head->unswitch_count() + 1 > head->unswitch_max()) { | |
68 return false; | |
69 } | |
70 return phase->find_unswitching_candidate(this) != NULL; | |
71 } | |
72 | |
73 //------------------------------find_unswitching_candidate----------------------------- | |
74 // Find candidate "if" for unswitching | |
75 IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop) const { | |
76 | |
77 // Find first invariant test that doesn't exit the loop | |
78 LoopNode *head = loop->_head->as_Loop(); | |
79 IfNode* unswitch_iff = NULL; | |
80 Node* n = head->in(LoopNode::LoopBackControl); | |
81 while (n != head) { | |
82 Node* n_dom = idom(n); | |
83 if (n->is_Region()) { | |
84 if (n_dom->is_If()) { | |
85 IfNode* iff = n_dom->as_If(); | |
86 if (iff->in(1)->is_Bool()) { | |
87 BoolNode* bol = iff->in(1)->as_Bool(); | |
88 if (bol->in(1)->is_Cmp()) { | |
89 // If condition is invariant and not a loop exit, | |
90 // then found reason to unswitch. | |
91 if (loop->is_invariant(bol) && !loop->is_loop_exit(iff)) { | |
92 unswitch_iff = iff; | |
93 } | |
94 } | |
95 } | |
96 } | |
97 } | |
98 n = n_dom; | |
99 } | |
100 return unswitch_iff; | |
101 } | |
102 | |
103 //------------------------------do_unswitching----------------------------- | |
104 // Clone loop with an invariant test (that does not exit) and | |
105 // insert a clone of the test that selects which version to | |
106 // execute. | |
107 void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) { | |
108 | |
109 // Find first invariant test that doesn't exit the loop | |
110 LoopNode *head = loop->_head->as_Loop(); | |
111 | |
112 IfNode* unswitch_iff = find_unswitching_candidate((const IdealLoopTree *)loop); | |
113 assert(unswitch_iff != NULL, "should be at least one"); | |
114 | |
2383
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
115 #ifndef PRODUCT |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
116 if (TraceLoopOpts) { |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
117 tty->print("Unswitch %d ", head->unswitch_count()+1); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
118 loop->dump_head(); |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
119 } |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
120 #endif |
9dc311b8473e
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
1972
diff
changeset
|
121 |
0 | 122 // Need to revert back to normal loop |
123 if (head->is_CountedLoop() && !head->as_CountedLoop()->is_normal_loop()) { | |
124 head->as_CountedLoop()->set_normal_loop(); | |
125 } | |
126 | |
127 ProjNode* proj_true = create_slow_version_of_loop(loop, old_new); | |
128 | |
2445 | 129 #ifdef ASSERT |
130 Node* uniqc = proj_true->unique_ctrl_out(); | |
131 Node* entry = head->in(LoopNode::EntryControl); | |
132 Node* predicate = find_predicate(entry); | |
3345 | 133 if (predicate != NULL && LoopLimitCheck && UseLoopPredicate) { |
134 // We may have two predicates, find first. | |
135 entry = find_predicate(entry->in(0)->in(0)); | |
136 if (entry != NULL) predicate = entry; | |
137 } | |
2445 | 138 if (predicate != NULL) predicate = predicate->in(0); |
139 assert(proj_true->is_IfTrue() && | |
140 (predicate == NULL && uniqc == head || | |
141 predicate != NULL && uniqc == predicate), "by construction"); | |
142 #endif | |
0 | 143 // Increment unswitch count |
144 LoopNode* head_clone = old_new[head->_idx]->as_Loop(); | |
145 int nct = head->unswitch_count() + 1; | |
146 head->set_unswitch_count(nct); | |
147 head_clone->set_unswitch_count(nct); | |
148 | |
149 // Add test to new "if" outside of loop | |
150 IfNode* invar_iff = proj_true->in(0)->as_If(); | |
151 Node* invar_iff_c = invar_iff->in(0); | |
152 BoolNode* bol = unswitch_iff->in(1)->as_Bool(); | |
153 invar_iff->set_req(1, bol); | |
154 invar_iff->_prob = unswitch_iff->_prob; | |
155 | |
156 ProjNode* proj_false = invar_iff->proj_out(0)->as_Proj(); | |
157 | |
605 | 158 // Hoist invariant casts out of each loop to the appropriate |
0 | 159 // control projection. |
160 | |
161 Node_List worklist; | |
162 | |
163 for (DUIterator_Fast imax, i = unswitch_iff->fast_outs(imax); i < imax; i++) { | |
164 ProjNode* proj= unswitch_iff->fast_out(i)->as_Proj(); | |
165 // Copy to a worklist for easier manipulation | |
166 for (DUIterator_Fast jmax, j = proj->fast_outs(jmax); j < jmax; j++) { | |
167 Node* use = proj->fast_out(j); | |
168 if (use->Opcode() == Op_CheckCastPP && loop->is_invariant(use->in(1))) { | |
169 worklist.push(use); | |
170 } | |
171 } | |
172 ProjNode* invar_proj = invar_iff->proj_out(proj->_con)->as_Proj(); | |
173 while (worklist.size() > 0) { | |
174 Node* use = worklist.pop(); | |
175 Node* nuse = use->clone(); | |
176 nuse->set_req(0, invar_proj); | |
177 _igvn.hash_delete(use); | |
178 use->set_req(1, nuse); | |
179 _igvn._worklist.push(use); | |
180 register_new_node(nuse, invar_proj); | |
181 // Same for the clone | |
182 Node* use_clone = old_new[use->_idx]; | |
183 _igvn.hash_delete(use_clone); | |
184 use_clone->set_req(1, nuse); | |
185 _igvn._worklist.push(use_clone); | |
186 } | |
187 } | |
188 | |
189 // Hardwire the control paths in the loops into if(true) and if(false) | |
190 _igvn.hash_delete(unswitch_iff); | |
191 short_circuit_if(unswitch_iff, proj_true); | |
192 _igvn._worklist.push(unswitch_iff); | |
193 | |
194 IfNode* unswitch_iff_clone = old_new[unswitch_iff->_idx]->as_If(); | |
195 _igvn.hash_delete(unswitch_iff_clone); | |
196 short_circuit_if(unswitch_iff_clone, proj_false); | |
197 _igvn._worklist.push(unswitch_iff_clone); | |
198 | |
199 // Reoptimize loops | |
200 loop->record_for_igvn(); | |
201 for(int i = loop->_body.size() - 1; i >= 0 ; i--) { | |
202 Node *n = loop->_body[i]; | |
203 Node *n_clone = old_new[n->_idx]; | |
204 _igvn._worklist.push(n_clone); | |
205 } | |
206 | |
207 #ifndef PRODUCT | |
208 if (TraceLoopUnswitching) { | |
209 tty->print_cr("Loop unswitching orig: %d @ %d new: %d @ %d", | |
210 head->_idx, unswitch_iff->_idx, | |
211 old_new[head->_idx]->_idx, unswitch_iff_clone->_idx); | |
212 } | |
213 #endif | |
214 | |
215 C->set_major_progress(); | |
216 } | |
217 | |
218 //-------------------------create_slow_version_of_loop------------------------ | |
219 // Create a slow version of the loop by cloning the loop | |
220 // and inserting an if to select fast-slow versions. | |
221 // Return control projection of the entry to the fast version. | |
222 ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop, | |
223 Node_List &old_new) { | |
224 LoopNode* head = loop->_head->as_Loop(); | |
3345 | 225 bool counted_loop = head->is_CountedLoop(); |
0 | 226 Node* entry = head->in(LoopNode::EntryControl); |
227 _igvn.hash_delete(entry); | |
228 _igvn._worklist.push(entry); | |
229 IdealLoopTree* outer_loop = loop->_parent; | |
230 | |
231 Node *cont = _igvn.intcon(1); | |
232 set_ctrl(cont, C->root()); | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
108
diff
changeset
|
233 Node* opq = new (C, 2) Opaque1Node(C, cont); |
0 | 234 register_node(opq, outer_loop, entry, dom_depth(entry)); |
235 Node *bol = new (C, 2) Conv2BNode(opq); | |
236 register_node(bol, outer_loop, entry, dom_depth(entry)); | |
237 IfNode* iff = new (C, 2) IfNode(entry, bol, PROB_MAX, COUNT_UNKNOWN); | |
238 register_node(iff, outer_loop, entry, dom_depth(entry)); | |
239 ProjNode* iffast = new (C, 1) IfTrueNode(iff); | |
240 register_node(iffast, outer_loop, iff, dom_depth(iff)); | |
241 ProjNode* ifslow = new (C, 1) IfFalseNode(iff); | |
242 register_node(ifslow, outer_loop, iff, dom_depth(iff)); | |
243 | |
244 // Clone the loop body. The clone becomes the fast loop. The | |
2445 | 245 // original pre-header will (illegally) have 3 control users |
246 // (old & new loops & new if). | |
0 | 247 clone_loop(loop, old_new, dom_depth(head), iff); |
248 assert(old_new[head->_idx]->is_Loop(), "" ); | |
249 | |
250 // Fast (true) control | |
3345 | 251 Node* iffast_pred = clone_loop_predicates(entry, iffast, !counted_loop); |
0 | 252 _igvn.hash_delete(head); |
2445 | 253 head->set_req(LoopNode::EntryControl, iffast_pred); |
254 set_idom(head, iffast_pred, dom_depth(head)); | |
0 | 255 _igvn._worklist.push(head); |
256 | |
257 // Slow (false) control | |
3845
c96c3eb1efae
7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents:
3345
diff
changeset
|
258 Node* ifslow_pred = clone_loop_predicates(entry, ifslow, !counted_loop); |
0 | 259 LoopNode* slow_head = old_new[head->_idx]->as_Loop(); |
260 _igvn.hash_delete(slow_head); | |
2445 | 261 slow_head->set_req(LoopNode::EntryControl, ifslow_pred); |
262 set_idom(slow_head, ifslow_pred, dom_depth(slow_head)); | |
0 | 263 _igvn._worklist.push(slow_head); |
264 | |
265 recompute_dom_depth(); | |
266 | |
267 return iffast; | |
268 } |