Mercurial > hg > truffle
annotate src/share/vm/opto/loopUnswitch.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | f95d63e2154a |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
2 * Copyright (c) 2006, 2008, 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 | |
25 #include "incls/_precompiled.incl" | |
26 #include "incls/_loopUnswitch.cpp.incl" | |
27 | |
28 //================= Loop Unswitching ===================== | |
29 // | |
30 // orig: transformed: | |
31 // if (invariant-test) then | |
32 // loop loop | |
33 // stmt1 stmt1 | |
34 // if (invariant-test) then stmt2 | |
35 // stmt2 stmt4 | |
36 // else endloop | |
37 // stmt3 else | |
38 // endif loop [clone] | |
39 // stmt4 stmt1 [clone] | |
40 // endloop stmt3 | |
41 // stmt4 [clone] | |
42 // endloop | |
43 // endif | |
44 // | |
45 // Note: the "else" clause may be empty | |
46 | |
47 //------------------------------policy_unswitching----------------------------- | |
48 // Return TRUE or FALSE if the loop should be unswitched | |
49 // (ie. clone loop with an invariant test that does not exit the loop) | |
50 bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { | |
51 if( !LoopUnswitching ) { | |
52 return false; | |
53 } | |
108 | 54 if (!_head->is_Loop()) { |
55 return false; | |
56 } | |
0 | 57 uint nodes_left = MaxNodeLimit - phase->C->unique(); |
58 if (2 * _body.size() > nodes_left) { | |
59 return false; // Too speculative if running low on nodes. | |
60 } | |
61 LoopNode* head = _head->as_Loop(); | |
62 if (head->unswitch_count() + 1 > head->unswitch_max()) { | |
63 return false; | |
64 } | |
65 return phase->find_unswitching_candidate(this) != NULL; | |
66 } | |
67 | |
68 //------------------------------find_unswitching_candidate----------------------------- | |
69 // Find candidate "if" for unswitching | |
70 IfNode* PhaseIdealLoop::find_unswitching_candidate(const IdealLoopTree *loop) const { | |
71 | |
72 // Find first invariant test that doesn't exit the loop | |
73 LoopNode *head = loop->_head->as_Loop(); | |
74 IfNode* unswitch_iff = NULL; | |
75 Node* n = head->in(LoopNode::LoopBackControl); | |
76 while (n != head) { | |
77 Node* n_dom = idom(n); | |
78 if (n->is_Region()) { | |
79 if (n_dom->is_If()) { | |
80 IfNode* iff = n_dom->as_If(); | |
81 if (iff->in(1)->is_Bool()) { | |
82 BoolNode* bol = iff->in(1)->as_Bool(); | |
83 if (bol->in(1)->is_Cmp()) { | |
84 // If condition is invariant and not a loop exit, | |
85 // then found reason to unswitch. | |
86 if (loop->is_invariant(bol) && !loop->is_loop_exit(iff)) { | |
87 unswitch_iff = iff; | |
88 } | |
89 } | |
90 } | |
91 } | |
92 } | |
93 n = n_dom; | |
94 } | |
95 return unswitch_iff; | |
96 } | |
97 | |
98 //------------------------------do_unswitching----------------------------- | |
99 // Clone loop with an invariant test (that does not exit) and | |
100 // insert a clone of the test that selects which version to | |
101 // execute. | |
102 void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) { | |
103 | |
104 // Find first invariant test that doesn't exit the loop | |
105 LoopNode *head = loop->_head->as_Loop(); | |
106 | |
107 IfNode* unswitch_iff = find_unswitching_candidate((const IdealLoopTree *)loop); | |
108 assert(unswitch_iff != NULL, "should be at least one"); | |
109 | |
110 // Need to revert back to normal loop | |
111 if (head->is_CountedLoop() && !head->as_CountedLoop()->is_normal_loop()) { | |
112 head->as_CountedLoop()->set_normal_loop(); | |
113 } | |
114 | |
115 ProjNode* proj_true = create_slow_version_of_loop(loop, old_new); | |
116 | |
117 assert(proj_true->is_IfTrue() && proj_true->unique_ctrl_out() == head, "by construction"); | |
118 | |
119 // Increment unswitch count | |
120 LoopNode* head_clone = old_new[head->_idx]->as_Loop(); | |
121 int nct = head->unswitch_count() + 1; | |
122 head->set_unswitch_count(nct); | |
123 head_clone->set_unswitch_count(nct); | |
124 | |
125 // Add test to new "if" outside of loop | |
126 IfNode* invar_iff = proj_true->in(0)->as_If(); | |
127 Node* invar_iff_c = invar_iff->in(0); | |
128 BoolNode* bol = unswitch_iff->in(1)->as_Bool(); | |
129 invar_iff->set_req(1, bol); | |
130 invar_iff->_prob = unswitch_iff->_prob; | |
131 | |
132 ProjNode* proj_false = invar_iff->proj_out(0)->as_Proj(); | |
133 | |
605 | 134 // Hoist invariant casts out of each loop to the appropriate |
0 | 135 // control projection. |
136 | |
137 Node_List worklist; | |
138 | |
139 for (DUIterator_Fast imax, i = unswitch_iff->fast_outs(imax); i < imax; i++) { | |
140 ProjNode* proj= unswitch_iff->fast_out(i)->as_Proj(); | |
141 // Copy to a worklist for easier manipulation | |
142 for (DUIterator_Fast jmax, j = proj->fast_outs(jmax); j < jmax; j++) { | |
143 Node* use = proj->fast_out(j); | |
144 if (use->Opcode() == Op_CheckCastPP && loop->is_invariant(use->in(1))) { | |
145 worklist.push(use); | |
146 } | |
147 } | |
148 ProjNode* invar_proj = invar_iff->proj_out(proj->_con)->as_Proj(); | |
149 while (worklist.size() > 0) { | |
150 Node* use = worklist.pop(); | |
151 Node* nuse = use->clone(); | |
152 nuse->set_req(0, invar_proj); | |
153 _igvn.hash_delete(use); | |
154 use->set_req(1, nuse); | |
155 _igvn._worklist.push(use); | |
156 register_new_node(nuse, invar_proj); | |
157 // Same for the clone | |
158 Node* use_clone = old_new[use->_idx]; | |
159 _igvn.hash_delete(use_clone); | |
160 use_clone->set_req(1, nuse); | |
161 _igvn._worklist.push(use_clone); | |
162 } | |
163 } | |
164 | |
165 // Hardwire the control paths in the loops into if(true) and if(false) | |
166 _igvn.hash_delete(unswitch_iff); | |
167 short_circuit_if(unswitch_iff, proj_true); | |
168 _igvn._worklist.push(unswitch_iff); | |
169 | |
170 IfNode* unswitch_iff_clone = old_new[unswitch_iff->_idx]->as_If(); | |
171 _igvn.hash_delete(unswitch_iff_clone); | |
172 short_circuit_if(unswitch_iff_clone, proj_false); | |
173 _igvn._worklist.push(unswitch_iff_clone); | |
174 | |
175 // Reoptimize loops | |
176 loop->record_for_igvn(); | |
177 for(int i = loop->_body.size() - 1; i >= 0 ; i--) { | |
178 Node *n = loop->_body[i]; | |
179 Node *n_clone = old_new[n->_idx]; | |
180 _igvn._worklist.push(n_clone); | |
181 } | |
182 | |
183 #ifndef PRODUCT | |
184 if (TraceLoopUnswitching) { | |
185 tty->print_cr("Loop unswitching orig: %d @ %d new: %d @ %d", | |
186 head->_idx, unswitch_iff->_idx, | |
187 old_new[head->_idx]->_idx, unswitch_iff_clone->_idx); | |
188 } | |
189 #endif | |
190 | |
191 C->set_major_progress(); | |
192 } | |
193 | |
194 //-------------------------create_slow_version_of_loop------------------------ | |
195 // Create a slow version of the loop by cloning the loop | |
196 // and inserting an if to select fast-slow versions. | |
197 // Return control projection of the entry to the fast version. | |
198 ProjNode* PhaseIdealLoop::create_slow_version_of_loop(IdealLoopTree *loop, | |
199 Node_List &old_new) { | |
200 LoopNode* head = loop->_head->as_Loop(); | |
201 Node* entry = head->in(LoopNode::EntryControl); | |
202 _igvn.hash_delete(entry); | |
203 _igvn._worklist.push(entry); | |
204 IdealLoopTree* outer_loop = loop->_parent; | |
205 | |
206 Node *cont = _igvn.intcon(1); | |
207 set_ctrl(cont, C->root()); | |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
108
diff
changeset
|
208 Node* opq = new (C, 2) Opaque1Node(C, cont); |
0 | 209 register_node(opq, outer_loop, entry, dom_depth(entry)); |
210 Node *bol = new (C, 2) Conv2BNode(opq); | |
211 register_node(bol, outer_loop, entry, dom_depth(entry)); | |
212 IfNode* iff = new (C, 2) IfNode(entry, bol, PROB_MAX, COUNT_UNKNOWN); | |
213 register_node(iff, outer_loop, entry, dom_depth(entry)); | |
214 ProjNode* iffast = new (C, 1) IfTrueNode(iff); | |
215 register_node(iffast, outer_loop, iff, dom_depth(iff)); | |
216 ProjNode* ifslow = new (C, 1) IfFalseNode(iff); | |
217 register_node(ifslow, outer_loop, iff, dom_depth(iff)); | |
218 | |
219 // Clone the loop body. The clone becomes the fast loop. The | |
220 // original pre-header will (illegally) have 2 control users (old & new loops). | |
221 clone_loop(loop, old_new, dom_depth(head), iff); | |
222 assert(old_new[head->_idx]->is_Loop(), "" ); | |
223 | |
224 // Fast (true) control | |
225 _igvn.hash_delete(head); | |
226 head->set_req(LoopNode::EntryControl, iffast); | |
227 set_idom(head, iffast, dom_depth(head)); | |
228 _igvn._worklist.push(head); | |
229 | |
230 // Slow (false) control | |
231 LoopNode* slow_head = old_new[head->_idx]->as_Loop(); | |
232 _igvn.hash_delete(slow_head); | |
233 slow_head->set_req(LoopNode::EntryControl, ifslow); | |
234 set_idom(slow_head, ifslow, dom_depth(slow_head)); | |
235 _igvn._worklist.push(slow_head); | |
236 | |
237 recompute_dom_depth(); | |
238 | |
239 return iffast; | |
240 } |