annotate src/share/vm/opto/loopTransform.cpp @ 1941:79d04223b8a5

Added caching for resolved types and resolved fields. This is crucial, because the local load elimination will lead to wrong results, if field equality (of two RiField objects with the same object and the same RiType) is not given. The caching makes sure that the default equals implementation is sufficient.
author Thomas Wuerthinger <wuerthinger@ssw.jku.at>
date Tue, 28 Dec 2010 18:33:26 +0100
parents 75588558f1bf
children f95d63e2154a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1303
diff changeset
2 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1303
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1303
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: 1303
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 #include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 #include "incls/_loopTransform.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 //------------------------------is_loop_exit-----------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
29 // Given an IfNode, return the loop-exiting projection or NULL if both
a61af66fc99e Initial load
duke
parents:
diff changeset
30 // arms remain in the loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
31 Node *IdealLoopTree::is_loop_exit(Node *iff) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
32 if( iff->outcnt() != 2 ) return NULL; // Ignore partially dead tests
a61af66fc99e Initial load
duke
parents:
diff changeset
33 PhaseIdealLoop *phase = _phase;
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // Test is an IfNode, has 2 projections. If BOTH are in the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // we need loop unswitching instead of peeling.
a61af66fc99e Initial load
duke
parents:
diff changeset
36 if( !is_member(phase->get_loop( iff->raw_out(0) )) )
a61af66fc99e Initial load
duke
parents:
diff changeset
37 return iff->raw_out(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
38 if( !is_member(phase->get_loop( iff->raw_out(1) )) )
a61af66fc99e Initial load
duke
parents:
diff changeset
39 return iff->raw_out(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
40 return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
41 }
a61af66fc99e Initial load
duke
parents:
diff changeset
42
a61af66fc99e Initial load
duke
parents:
diff changeset
43
a61af66fc99e Initial load
duke
parents:
diff changeset
44 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
45
a61af66fc99e Initial load
duke
parents:
diff changeset
46
a61af66fc99e Initial load
duke
parents:
diff changeset
47 //------------------------------record_for_igvn----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
48 // Put loop body on igvn work list
a61af66fc99e Initial load
duke
parents:
diff changeset
49 void IdealLoopTree::record_for_igvn() {
a61af66fc99e Initial load
duke
parents:
diff changeset
50 for( uint i = 0; i < _body.size(); i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
51 Node *n = _body.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
52 _phase->_igvn._worklist.push(n);
a61af66fc99e Initial load
duke
parents:
diff changeset
53 }
a61af66fc99e Initial load
duke
parents:
diff changeset
54 }
a61af66fc99e Initial load
duke
parents:
diff changeset
55
a61af66fc99e Initial load
duke
parents:
diff changeset
56 //------------------------------compute_profile_trip_cnt----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
57 // Compute loop trip count from profile data as
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // (backedge_count + loop_exit_count) / loop_exit_count
a61af66fc99e Initial load
duke
parents:
diff changeset
59 void IdealLoopTree::compute_profile_trip_cnt( PhaseIdealLoop *phase ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
60 if (!_head->is_CountedLoop()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
61 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
62 }
a61af66fc99e Initial load
duke
parents:
diff changeset
63 CountedLoopNode* head = _head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
64 if (head->profile_trip_cnt() != COUNT_UNKNOWN) {
a61af66fc99e Initial load
duke
parents:
diff changeset
65 return; // Already computed
a61af66fc99e Initial load
duke
parents:
diff changeset
66 }
a61af66fc99e Initial load
duke
parents:
diff changeset
67 float trip_cnt = (float)max_jint; // default is big
a61af66fc99e Initial load
duke
parents:
diff changeset
68
a61af66fc99e Initial load
duke
parents:
diff changeset
69 Node* back = head->in(LoopNode::LoopBackControl);
a61af66fc99e Initial load
duke
parents:
diff changeset
70 while (back != head) {
a61af66fc99e Initial load
duke
parents:
diff changeset
71 if ((back->Opcode() == Op_IfTrue || back->Opcode() == Op_IfFalse) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
72 back->in(0) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
73 back->in(0)->is_If() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
74 back->in(0)->as_If()->_fcnt != COUNT_UNKNOWN &&
a61af66fc99e Initial load
duke
parents:
diff changeset
75 back->in(0)->as_If()->_prob != PROB_UNKNOWN) {
a61af66fc99e Initial load
duke
parents:
diff changeset
76 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
77 }
a61af66fc99e Initial load
duke
parents:
diff changeset
78 back = phase->idom(back);
a61af66fc99e Initial load
duke
parents:
diff changeset
79 }
a61af66fc99e Initial load
duke
parents:
diff changeset
80 if (back != head) {
a61af66fc99e Initial load
duke
parents:
diff changeset
81 assert((back->Opcode() == Op_IfTrue || back->Opcode() == Op_IfFalse) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
82 back->in(0), "if-projection exists");
a61af66fc99e Initial load
duke
parents:
diff changeset
83 IfNode* back_if = back->in(0)->as_If();
a61af66fc99e Initial load
duke
parents:
diff changeset
84 float loop_back_cnt = back_if->_fcnt * back_if->_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
85
a61af66fc99e Initial load
duke
parents:
diff changeset
86 // Now compute a loop exit count
a61af66fc99e Initial load
duke
parents:
diff changeset
87 float loop_exit_cnt = 0.0f;
a61af66fc99e Initial load
duke
parents:
diff changeset
88 for( uint i = 0; i < _body.size(); i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
89 Node *n = _body[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
90 if( n->is_If() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
91 IfNode *iff = n->as_If();
a61af66fc99e Initial load
duke
parents:
diff changeset
92 if( iff->_fcnt != COUNT_UNKNOWN && iff->_prob != PROB_UNKNOWN ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
93 Node *exit = is_loop_exit(iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
94 if( exit ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
95 float exit_prob = iff->_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
96 if (exit->Opcode() == Op_IfFalse) exit_prob = 1.0 - exit_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
97 if (exit_prob > PROB_MIN) {
a61af66fc99e Initial load
duke
parents:
diff changeset
98 float exit_cnt = iff->_fcnt * exit_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
99 loop_exit_cnt += exit_cnt;
a61af66fc99e Initial load
duke
parents:
diff changeset
100 }
a61af66fc99e Initial load
duke
parents:
diff changeset
101 }
a61af66fc99e Initial load
duke
parents:
diff changeset
102 }
a61af66fc99e Initial load
duke
parents:
diff changeset
103 }
a61af66fc99e Initial load
duke
parents:
diff changeset
104 }
a61af66fc99e Initial load
duke
parents:
diff changeset
105 if (loop_exit_cnt > 0.0f) {
a61af66fc99e Initial load
duke
parents:
diff changeset
106 trip_cnt = (loop_back_cnt + loop_exit_cnt) / loop_exit_cnt;
a61af66fc99e Initial load
duke
parents:
diff changeset
107 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 // No exit count so use
a61af66fc99e Initial load
duke
parents:
diff changeset
109 trip_cnt = loop_back_cnt;
a61af66fc99e Initial load
duke
parents:
diff changeset
110 }
a61af66fc99e Initial load
duke
parents:
diff changeset
111 }
a61af66fc99e Initial load
duke
parents:
diff changeset
112 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
113 if (TraceProfileTripCount) {
a61af66fc99e Initial load
duke
parents:
diff changeset
114 tty->print_cr("compute_profile_trip_cnt lp: %d cnt: %f\n", head->_idx, trip_cnt);
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
117 head->set_profile_trip_cnt(trip_cnt);
a61af66fc99e Initial load
duke
parents:
diff changeset
118 }
a61af66fc99e Initial load
duke
parents:
diff changeset
119
a61af66fc99e Initial load
duke
parents:
diff changeset
120 //---------------------is_invariant_addition-----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
121 // Return nonzero index of invariant operand for an Add or Sub
605
98cb887364d3 6810672: Comment typos
twisti
parents: 420
diff changeset
122 // of (nonconstant) invariant and variant values. Helper for reassociate_invariants.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
123 int IdealLoopTree::is_invariant_addition(Node* n, PhaseIdealLoop *phase) {
a61af66fc99e Initial load
duke
parents:
diff changeset
124 int op = n->Opcode();
a61af66fc99e Initial load
duke
parents:
diff changeset
125 if (op == Op_AddI || op == Op_SubI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
126 bool in1_invar = this->is_invariant(n->in(1));
a61af66fc99e Initial load
duke
parents:
diff changeset
127 bool in2_invar = this->is_invariant(n->in(2));
a61af66fc99e Initial load
duke
parents:
diff changeset
128 if (in1_invar && !in2_invar) return 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
129 if (!in1_invar && in2_invar) return 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
130 }
a61af66fc99e Initial load
duke
parents:
diff changeset
131 return 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
133
a61af66fc99e Initial load
duke
parents:
diff changeset
134 //---------------------reassociate_add_sub-----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
135 // Reassociate invariant add and subtract expressions:
a61af66fc99e Initial load
duke
parents:
diff changeset
136 //
a61af66fc99e Initial load
duke
parents:
diff changeset
137 // inv1 + (x + inv2) => ( inv1 + inv2) + x
a61af66fc99e Initial load
duke
parents:
diff changeset
138 // (x + inv2) + inv1 => ( inv1 + inv2) + x
a61af66fc99e Initial load
duke
parents:
diff changeset
139 // inv1 + (x - inv2) => ( inv1 - inv2) + x
a61af66fc99e Initial load
duke
parents:
diff changeset
140 // inv1 - (inv2 - x) => ( inv1 - inv2) + x
a61af66fc99e Initial load
duke
parents:
diff changeset
141 // (x + inv2) - inv1 => (-inv1 + inv2) + x
a61af66fc99e Initial load
duke
parents:
diff changeset
142 // (x - inv2) + inv1 => ( inv1 - inv2) + x
a61af66fc99e Initial load
duke
parents:
diff changeset
143 // (x - inv2) - inv1 => (-inv1 - inv2) + x
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // inv1 + (inv2 - x) => ( inv1 + inv2) - x
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // inv1 - (x - inv2) => ( inv1 + inv2) - x
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // (inv2 - x) + inv1 => ( inv1 + inv2) - x
a61af66fc99e Initial load
duke
parents:
diff changeset
147 // (inv2 - x) - inv1 => (-inv1 + inv2) - x
a61af66fc99e Initial load
duke
parents:
diff changeset
148 // inv1 - (x + inv2) => ( inv1 - inv2) - x
a61af66fc99e Initial load
duke
parents:
diff changeset
149 //
a61af66fc99e Initial load
duke
parents:
diff changeset
150 Node* IdealLoopTree::reassociate_add_sub(Node* n1, PhaseIdealLoop *phase) {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 if (!n1->is_Add() && !n1->is_Sub() || n1->outcnt() == 0) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
152 if (is_invariant(n1)) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
153 int inv1_idx = is_invariant_addition(n1, phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
154 if (!inv1_idx) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
155 // Don't mess with add of constant (igvn moves them to expression tree root.)
a61af66fc99e Initial load
duke
parents:
diff changeset
156 if (n1->is_Add() && n1->in(2)->is_Con()) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
157 Node* inv1 = n1->in(inv1_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
158 Node* n2 = n1->in(3 - inv1_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
159 int inv2_idx = is_invariant_addition(n2, phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
160 if (!inv2_idx) return NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 Node* x = n2->in(3 - inv2_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
162 Node* inv2 = n2->in(inv2_idx);
a61af66fc99e Initial load
duke
parents:
diff changeset
163
a61af66fc99e Initial load
duke
parents:
diff changeset
164 bool neg_x = n2->is_Sub() && inv2_idx == 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
165 bool neg_inv2 = n2->is_Sub() && inv2_idx == 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
166 bool neg_inv1 = n1->is_Sub() && inv1_idx == 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
167 if (n1->is_Sub() && inv1_idx == 1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
168 neg_x = !neg_x;
a61af66fc99e Initial load
duke
parents:
diff changeset
169 neg_inv2 = !neg_inv2;
a61af66fc99e Initial load
duke
parents:
diff changeset
170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
171 Node* inv1_c = phase->get_ctrl(inv1);
a61af66fc99e Initial load
duke
parents:
diff changeset
172 Node* inv2_c = phase->get_ctrl(inv2);
a61af66fc99e Initial load
duke
parents:
diff changeset
173 Node* n_inv1;
a61af66fc99e Initial load
duke
parents:
diff changeset
174 if (neg_inv1) {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 Node *zero = phase->_igvn.intcon(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
176 phase->set_ctrl(zero, phase->C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
177 n_inv1 = new (phase->C, 3) SubINode(zero, inv1);
a61af66fc99e Initial load
duke
parents:
diff changeset
178 phase->register_new_node(n_inv1, inv1_c);
a61af66fc99e Initial load
duke
parents:
diff changeset
179 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
180 n_inv1 = inv1;
a61af66fc99e Initial load
duke
parents:
diff changeset
181 }
a61af66fc99e Initial load
duke
parents:
diff changeset
182 Node* inv;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 if (neg_inv2) {
a61af66fc99e Initial load
duke
parents:
diff changeset
184 inv = new (phase->C, 3) SubINode(n_inv1, inv2);
a61af66fc99e Initial load
duke
parents:
diff changeset
185 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
186 inv = new (phase->C, 3) AddINode(n_inv1, inv2);
a61af66fc99e Initial load
duke
parents:
diff changeset
187 }
a61af66fc99e Initial load
duke
parents:
diff changeset
188 phase->register_new_node(inv, phase->get_early_ctrl(inv));
a61af66fc99e Initial load
duke
parents:
diff changeset
189
a61af66fc99e Initial load
duke
parents:
diff changeset
190 Node* addx;
a61af66fc99e Initial load
duke
parents:
diff changeset
191 if (neg_x) {
a61af66fc99e Initial load
duke
parents:
diff changeset
192 addx = new (phase->C, 3) SubINode(inv, x);
a61af66fc99e Initial load
duke
parents:
diff changeset
193 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
194 addx = new (phase->C, 3) AddINode(x, inv);
a61af66fc99e Initial load
duke
parents:
diff changeset
195 }
a61af66fc99e Initial load
duke
parents:
diff changeset
196 phase->register_new_node(addx, phase->get_ctrl(x));
1621
6027dddc26c6 6677629: PhaseIterGVN::subsume_node() should call hash_delete() and add_users_to_worklist()
kvn
parents: 1552
diff changeset
197 phase->_igvn.replace_node(n1, addx);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
198 return addx;
a61af66fc99e Initial load
duke
parents:
diff changeset
199 }
a61af66fc99e Initial load
duke
parents:
diff changeset
200
a61af66fc99e Initial load
duke
parents:
diff changeset
201 //---------------------reassociate_invariants-----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // Reassociate invariant expressions:
a61af66fc99e Initial load
duke
parents:
diff changeset
203 void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) {
a61af66fc99e Initial load
duke
parents:
diff changeset
204 for (int i = _body.size() - 1; i >= 0; i--) {
a61af66fc99e Initial load
duke
parents:
diff changeset
205 Node *n = _body.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
206 for (int j = 0; j < 5; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
207 Node* nn = reassociate_add_sub(n, phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
208 if (nn == NULL) break;
a61af66fc99e Initial load
duke
parents:
diff changeset
209 n = nn; // again
a61af66fc99e Initial load
duke
parents:
diff changeset
210 };
a61af66fc99e Initial load
duke
parents:
diff changeset
211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
213
a61af66fc99e Initial load
duke
parents:
diff changeset
214 //------------------------------policy_peeling---------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
215 // Return TRUE or FALSE if the loop should be peeled or not. Peel if we can
a61af66fc99e Initial load
duke
parents:
diff changeset
216 // make some loop-invariant test (usually a null-check) happen before the loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
217 bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
218 Node *test = ((IdealLoopTree*)this)->tail();
a61af66fc99e Initial load
duke
parents:
diff changeset
219 int body_size = ((IdealLoopTree*)this)->_body.size();
a61af66fc99e Initial load
duke
parents:
diff changeset
220 int uniq = phase->C->unique();
a61af66fc99e Initial load
duke
parents:
diff changeset
221 // Peeling does loop cloning which can result in O(N^2) node construction
a61af66fc99e Initial load
duke
parents:
diff changeset
222 if( body_size > 255 /* Prevent overflow for large body_size */
a61af66fc99e Initial load
duke
parents:
diff changeset
223 || (body_size * body_size + uniq > MaxNodeLimit) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
224 return false; // too large to safely clone
a61af66fc99e Initial load
duke
parents:
diff changeset
225 }
a61af66fc99e Initial load
duke
parents:
diff changeset
226 while( test != _head ) { // Scan till run off top of loop
a61af66fc99e Initial load
duke
parents:
diff changeset
227 if( test->is_If() ) { // Test?
a61af66fc99e Initial load
duke
parents:
diff changeset
228 Node *ctrl = phase->get_ctrl(test->in(1));
a61af66fc99e Initial load
duke
parents:
diff changeset
229 if (ctrl->is_top())
a61af66fc99e Initial load
duke
parents:
diff changeset
230 return false; // Found dead test on live IF? No peeling!
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // Standard IF only has one input value to check for loop invariance
a61af66fc99e Initial load
duke
parents:
diff changeset
232 assert( test->Opcode() == Op_If || test->Opcode() == Op_CountedLoopEnd, "Check this code when new subtype is added");
a61af66fc99e Initial load
duke
parents:
diff changeset
233 // Condition is not a member of this loop?
a61af66fc99e Initial load
duke
parents:
diff changeset
234 if( !is_member(phase->get_loop(ctrl)) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
235 is_loop_exit(test) )
a61af66fc99e Initial load
duke
parents:
diff changeset
236 return true; // Found reason to peel!
a61af66fc99e Initial load
duke
parents:
diff changeset
237 }
a61af66fc99e Initial load
duke
parents:
diff changeset
238 // Walk up dominators to loop _head looking for test which is
a61af66fc99e Initial load
duke
parents:
diff changeset
239 // executed on every path thru loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
240 test = phase->idom(test);
a61af66fc99e Initial load
duke
parents:
diff changeset
241 }
a61af66fc99e Initial load
duke
parents:
diff changeset
242 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
243 }
a61af66fc99e Initial load
duke
parents:
diff changeset
244
a61af66fc99e Initial load
duke
parents:
diff changeset
245 //------------------------------peeled_dom_test_elim---------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
246 // If we got the effect of peeling, either by actually peeling or by making
a61af66fc99e Initial load
duke
parents:
diff changeset
247 // a pre-loop which must execute at least once, we can remove all
a61af66fc99e Initial load
duke
parents:
diff changeset
248 // loop-invariant dominated tests in the main body.
a61af66fc99e Initial load
duke
parents:
diff changeset
249 void PhaseIdealLoop::peeled_dom_test_elim( IdealLoopTree *loop, Node_List &old_new ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
250 bool progress = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
251 while( progress ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
252 progress = false; // Reset for next iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
253 Node *prev = loop->_head->in(LoopNode::LoopBackControl);//loop->tail();
a61af66fc99e Initial load
duke
parents:
diff changeset
254 Node *test = prev->in(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
255 while( test != loop->_head ) { // Scan till run off top of loop
a61af66fc99e Initial load
duke
parents:
diff changeset
256
a61af66fc99e Initial load
duke
parents:
diff changeset
257 int p_op = prev->Opcode();
a61af66fc99e Initial load
duke
parents:
diff changeset
258 if( (p_op == Op_IfFalse || p_op == Op_IfTrue) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
259 test->is_If() && // Test?
a61af66fc99e Initial load
duke
parents:
diff changeset
260 !test->in(1)->is_Con() && // And not already obvious?
a61af66fc99e Initial load
duke
parents:
diff changeset
261 // Condition is not a member of this loop?
a61af66fc99e Initial load
duke
parents:
diff changeset
262 !loop->is_member(get_loop(get_ctrl(test->in(1))))){
a61af66fc99e Initial load
duke
parents:
diff changeset
263 // Walk loop body looking for instances of this test
a61af66fc99e Initial load
duke
parents:
diff changeset
264 for( uint i = 0; i < loop->_body.size(); i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
265 Node *n = loop->_body.at(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
266 if( n->is_If() && n->in(1) == test->in(1) /*&& n != loop->tail()->in(0)*/ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
267 // IfNode was dominated by version in peeled loop body
a61af66fc99e Initial load
duke
parents:
diff changeset
268 progress = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
269 dominated_by( old_new[prev->_idx], n );
a61af66fc99e Initial load
duke
parents:
diff changeset
270 }
a61af66fc99e Initial load
duke
parents:
diff changeset
271 }
a61af66fc99e Initial load
duke
parents:
diff changeset
272 }
a61af66fc99e Initial load
duke
parents:
diff changeset
273 prev = test;
a61af66fc99e Initial load
duke
parents:
diff changeset
274 test = idom(test);
a61af66fc99e Initial load
duke
parents:
diff changeset
275 } // End of scan tests in loop
a61af66fc99e Initial load
duke
parents:
diff changeset
276
a61af66fc99e Initial load
duke
parents:
diff changeset
277 } // End of while( progress )
a61af66fc99e Initial load
duke
parents:
diff changeset
278 }
a61af66fc99e Initial load
duke
parents:
diff changeset
279
a61af66fc99e Initial load
duke
parents:
diff changeset
280 //------------------------------do_peeling-------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
281 // Peel the first iteration of the given loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
282 // Step 1: Clone the loop body. The clone becomes the peeled iteration.
a61af66fc99e Initial load
duke
parents:
diff changeset
283 // The pre-loop illegally has 2 control users (old & new loops).
a61af66fc99e Initial load
duke
parents:
diff changeset
284 // Step 2: Make the old-loop fall-in edges point to the peeled iteration.
a61af66fc99e Initial load
duke
parents:
diff changeset
285 // Do this by making the old-loop fall-in edges act as if they came
a61af66fc99e Initial load
duke
parents:
diff changeset
286 // around the loopback from the prior iteration (follow the old-loop
a61af66fc99e Initial load
duke
parents:
diff changeset
287 // backedges) and then map to the new peeled iteration. This leaves
a61af66fc99e Initial load
duke
parents:
diff changeset
288 // the pre-loop with only 1 user (the new peeled iteration), but the
a61af66fc99e Initial load
duke
parents:
diff changeset
289 // peeled-loop backedge has 2 users.
a61af66fc99e Initial load
duke
parents:
diff changeset
290 // Step 3: Cut the backedge on the clone (so its not a loop) and remove the
a61af66fc99e Initial load
duke
parents:
diff changeset
291 // extra backedge user.
a61af66fc99e Initial load
duke
parents:
diff changeset
292 void PhaseIdealLoop::do_peeling( IdealLoopTree *loop, Node_List &old_new ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
293
a61af66fc99e Initial load
duke
parents:
diff changeset
294 C->set_major_progress();
a61af66fc99e Initial load
duke
parents:
diff changeset
295 // Peeling a 'main' loop in a pre/main/post situation obfuscates the
a61af66fc99e Initial load
duke
parents:
diff changeset
296 // 'pre' loop from the main and the 'pre' can no longer have it's
a61af66fc99e Initial load
duke
parents:
diff changeset
297 // iterations adjusted. Therefore, we need to declare this loop as
a61af66fc99e Initial load
duke
parents:
diff changeset
298 // no longer a 'main' loop; it will need new pre and post loops before
a61af66fc99e Initial load
duke
parents:
diff changeset
299 // we can do further RCE.
a61af66fc99e Initial load
duke
parents:
diff changeset
300 Node *h = loop->_head;
a61af66fc99e Initial load
duke
parents:
diff changeset
301 if( h->is_CountedLoop() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
302 CountedLoopNode *cl = h->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
303 assert(cl->trip_count() > 0, "peeling a fully unrolled loop");
a61af66fc99e Initial load
duke
parents:
diff changeset
304 cl->set_trip_count(cl->trip_count() - 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
305 if( cl->is_main_loop() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
306 cl->set_normal_loop();
a61af66fc99e Initial load
duke
parents:
diff changeset
307 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
308 if( PrintOpto && VerifyLoopOptimizations ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
309 tty->print("Peeling a 'main' loop; resetting to 'normal' ");
a61af66fc99e Initial load
duke
parents:
diff changeset
310 loop->dump_head();
a61af66fc99e Initial load
duke
parents:
diff changeset
311 }
a61af66fc99e Initial load
duke
parents:
diff changeset
312 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
313 }
a61af66fc99e Initial load
duke
parents:
diff changeset
314 }
a61af66fc99e Initial load
duke
parents:
diff changeset
315
a61af66fc99e Initial load
duke
parents:
diff changeset
316 // Step 1: Clone the loop body. The clone becomes the peeled iteration.
a61af66fc99e Initial load
duke
parents:
diff changeset
317 // The pre-loop illegally has 2 control users (old & new loops).
a61af66fc99e Initial load
duke
parents:
diff changeset
318 clone_loop( loop, old_new, dom_depth(loop->_head) );
a61af66fc99e Initial load
duke
parents:
diff changeset
319
a61af66fc99e Initial load
duke
parents:
diff changeset
320
a61af66fc99e Initial load
duke
parents:
diff changeset
321 // Step 2: Make the old-loop fall-in edges point to the peeled iteration.
a61af66fc99e Initial load
duke
parents:
diff changeset
322 // Do this by making the old-loop fall-in edges act as if they came
a61af66fc99e Initial load
duke
parents:
diff changeset
323 // around the loopback from the prior iteration (follow the old-loop
a61af66fc99e Initial load
duke
parents:
diff changeset
324 // backedges) and then map to the new peeled iteration. This leaves
a61af66fc99e Initial load
duke
parents:
diff changeset
325 // the pre-loop with only 1 user (the new peeled iteration), but the
a61af66fc99e Initial load
duke
parents:
diff changeset
326 // peeled-loop backedge has 2 users.
a61af66fc99e Initial load
duke
parents:
diff changeset
327 for (DUIterator_Fast jmax, j = loop->_head->fast_outs(jmax); j < jmax; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
328 Node* old = loop->_head->fast_out(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
329 if( old->in(0) == loop->_head && old->req() == 3 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
330 (old->is_Loop() || old->is_Phi()) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
331 Node *new_exit_value = old_new[old->in(LoopNode::LoopBackControl)->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
332 if( !new_exit_value ) // Backedge value is ALSO loop invariant?
a61af66fc99e Initial load
duke
parents:
diff changeset
333 // Then loop body backedge value remains the same.
a61af66fc99e Initial load
duke
parents:
diff changeset
334 new_exit_value = old->in(LoopNode::LoopBackControl);
a61af66fc99e Initial load
duke
parents:
diff changeset
335 _igvn.hash_delete(old);
a61af66fc99e Initial load
duke
parents:
diff changeset
336 old->set_req(LoopNode::EntryControl, new_exit_value);
a61af66fc99e Initial load
duke
parents:
diff changeset
337 }
a61af66fc99e Initial load
duke
parents:
diff changeset
338 }
a61af66fc99e Initial load
duke
parents:
diff changeset
339
a61af66fc99e Initial load
duke
parents:
diff changeset
340
a61af66fc99e Initial load
duke
parents:
diff changeset
341 // Step 3: Cut the backedge on the clone (so its not a loop) and remove the
a61af66fc99e Initial load
duke
parents:
diff changeset
342 // extra backedge user.
a61af66fc99e Initial load
duke
parents:
diff changeset
343 Node *nnn = old_new[loop->_head->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
344 _igvn.hash_delete(nnn);
a61af66fc99e Initial load
duke
parents:
diff changeset
345 nnn->set_req(LoopNode::LoopBackControl, C->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
346 for (DUIterator_Fast j2max, j2 = nnn->fast_outs(j2max); j2 < j2max; j2++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
347 Node* use = nnn->fast_out(j2);
a61af66fc99e Initial load
duke
parents:
diff changeset
348 if( use->in(0) == nnn && use->req() == 3 && use->is_Phi() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
349 _igvn.hash_delete(use);
a61af66fc99e Initial load
duke
parents:
diff changeset
350 use->set_req(LoopNode::LoopBackControl, C->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
351 }
a61af66fc99e Initial load
duke
parents:
diff changeset
352 }
a61af66fc99e Initial load
duke
parents:
diff changeset
353
a61af66fc99e Initial load
duke
parents:
diff changeset
354
a61af66fc99e Initial load
duke
parents:
diff changeset
355 // Step 4: Correct dom-depth info. Set to loop-head depth.
a61af66fc99e Initial load
duke
parents:
diff changeset
356 int dd = dom_depth(loop->_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
357 set_idom(loop->_head, loop->_head->in(1), dd);
a61af66fc99e Initial load
duke
parents:
diff changeset
358 for (uint j3 = 0; j3 < loop->_body.size(); j3++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
359 Node *old = loop->_body.at(j3);
a61af66fc99e Initial load
duke
parents:
diff changeset
360 Node *nnn = old_new[old->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
361 if (!has_ctrl(nnn))
a61af66fc99e Initial load
duke
parents:
diff changeset
362 set_idom(nnn, idom(nnn), dd-1);
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // While we're at it, remove any SafePoints from the peeled code
a61af66fc99e Initial load
duke
parents:
diff changeset
364 if( old->Opcode() == Op_SafePoint ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
365 Node *nnn = old_new[old->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
366 lazy_replace(nnn,nnn->in(TypeFunc::Control));
a61af66fc99e Initial load
duke
parents:
diff changeset
367 }
a61af66fc99e Initial load
duke
parents:
diff changeset
368 }
a61af66fc99e Initial load
duke
parents:
diff changeset
369
a61af66fc99e Initial load
duke
parents:
diff changeset
370 // Now force out all loop-invariant dominating tests. The optimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
371 // finds some, but we _know_ they are all useless.
a61af66fc99e Initial load
duke
parents:
diff changeset
372 peeled_dom_test_elim(loop,old_new);
a61af66fc99e Initial load
duke
parents:
diff changeset
373
a61af66fc99e Initial load
duke
parents:
diff changeset
374 loop->record_for_igvn();
a61af66fc99e Initial load
duke
parents:
diff changeset
375 }
a61af66fc99e Initial load
duke
parents:
diff changeset
376
a61af66fc99e Initial load
duke
parents:
diff changeset
377 //------------------------------policy_maximally_unroll------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
378 // Return exact loop trip count, or 0 if not maximally unrolling
a61af66fc99e Initial load
duke
parents:
diff changeset
379 bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
380 CountedLoopNode *cl = _head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
381 assert( cl->is_normal_loop(), "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
382
a61af66fc99e Initial load
duke
parents:
diff changeset
383 Node *init_n = cl->init_trip();
a61af66fc99e Initial load
duke
parents:
diff changeset
384 Node *limit_n = cl->limit();
a61af66fc99e Initial load
duke
parents:
diff changeset
385
a61af66fc99e Initial load
duke
parents:
diff changeset
386 // Non-constant bounds
a61af66fc99e Initial load
duke
parents:
diff changeset
387 if( init_n == NULL || !init_n->is_Con() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
388 limit_n == NULL || !limit_n->is_Con() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
389 // protect against stride not being a constant
a61af66fc99e Initial load
duke
parents:
diff changeset
390 !cl->stride_is_con() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
391 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
392 }
a61af66fc99e Initial load
duke
parents:
diff changeset
393 int init = init_n->get_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
394 int limit = limit_n->get_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
395 int span = limit - init;
a61af66fc99e Initial load
duke
parents:
diff changeset
396 int stride = cl->stride_con();
a61af66fc99e Initial load
duke
parents:
diff changeset
397
a61af66fc99e Initial load
duke
parents:
diff changeset
398 if (init >= limit || stride > span) {
a61af66fc99e Initial load
duke
parents:
diff changeset
399 // return a false (no maximally unroll) and the regular unroll/peel
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // route will make a small mess which CCP will fold away.
a61af66fc99e Initial load
duke
parents:
diff changeset
401 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
402 }
a61af66fc99e Initial load
duke
parents:
diff changeset
403 uint trip_count = span/stride; // trip_count can be greater than 2 Gig.
a61af66fc99e Initial load
duke
parents:
diff changeset
404 assert( (int)trip_count*stride == span, "must divide evenly" );
a61af66fc99e Initial load
duke
parents:
diff changeset
405
a61af66fc99e Initial load
duke
parents:
diff changeset
406 // Real policy: if we maximally unroll, does it get too big?
a61af66fc99e Initial load
duke
parents:
diff changeset
407 // Allow the unrolled mess to get larger than standard loop
a61af66fc99e Initial load
duke
parents:
diff changeset
408 // size. After all, it will no longer be a loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
409 uint body_size = _body.size();
a61af66fc99e Initial load
duke
parents:
diff changeset
410 uint unroll_limit = (uint)LoopUnrollLimit * 4;
a61af66fc99e Initial load
duke
parents:
diff changeset
411 assert( (intx)unroll_limit == LoopUnrollLimit * 4, "LoopUnrollLimit must fit in 32bits");
a61af66fc99e Initial load
duke
parents:
diff changeset
412 cl->set_trip_count(trip_count);
a61af66fc99e Initial load
duke
parents:
diff changeset
413 if( trip_count <= unroll_limit && body_size <= unroll_limit ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
414 uint new_body_size = body_size * trip_count;
a61af66fc99e Initial load
duke
parents:
diff changeset
415 if (new_body_size <= unroll_limit &&
a61af66fc99e Initial load
duke
parents:
diff changeset
416 body_size == new_body_size / trip_count &&
a61af66fc99e Initial load
duke
parents:
diff changeset
417 // Unrolling can result in a large amount of node construction
a61af66fc99e Initial load
duke
parents:
diff changeset
418 new_body_size < MaxNodeLimit - phase->C->unique()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
419 return true; // maximally unroll
a61af66fc99e Initial load
duke
parents:
diff changeset
420 }
a61af66fc99e Initial load
duke
parents:
diff changeset
421 }
a61af66fc99e Initial load
duke
parents:
diff changeset
422
a61af66fc99e Initial load
duke
parents:
diff changeset
423 return false; // Do not maximally unroll
a61af66fc99e Initial load
duke
parents:
diff changeset
424 }
a61af66fc99e Initial load
duke
parents:
diff changeset
425
a61af66fc99e Initial load
duke
parents:
diff changeset
426
a61af66fc99e Initial load
duke
parents:
diff changeset
427 //------------------------------policy_unroll----------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
428 // Return TRUE or FALSE if the loop should be unrolled or not. Unroll if
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // the loop is a CountedLoop and the body is small enough.
a61af66fc99e Initial load
duke
parents:
diff changeset
430 bool IdealLoopTree::policy_unroll( PhaseIdealLoop *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
431
a61af66fc99e Initial load
duke
parents:
diff changeset
432 CountedLoopNode *cl = _head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
433 assert( cl->is_normal_loop() || cl->is_main_loop(), "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
434
a61af66fc99e Initial load
duke
parents:
diff changeset
435 // protect against stride not being a constant
a61af66fc99e Initial load
duke
parents:
diff changeset
436 if( !cl->stride_is_con() ) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
437
a61af66fc99e Initial load
duke
parents:
diff changeset
438 // protect against over-unrolling
a61af66fc99e Initial load
duke
parents:
diff changeset
439 if( cl->trip_count() <= 1 ) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
440
a61af66fc99e Initial load
duke
parents:
diff changeset
441 int future_unroll_ct = cl->unrolled_count() * 2;
a61af66fc99e Initial load
duke
parents:
diff changeset
442
a61af66fc99e Initial load
duke
parents:
diff changeset
443 // Don't unroll if the next round of unrolling would push us
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // over the expected trip count of the loop. One is subtracted
a61af66fc99e Initial load
duke
parents:
diff changeset
445 // from the expected trip count because the pre-loop normally
a61af66fc99e Initial load
duke
parents:
diff changeset
446 // executes 1 iteration.
a61af66fc99e Initial load
duke
parents:
diff changeset
447 if (UnrollLimitForProfileCheck > 0 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
448 cl->profile_trip_cnt() != COUNT_UNKNOWN &&
a61af66fc99e Initial load
duke
parents:
diff changeset
449 future_unroll_ct > UnrollLimitForProfileCheck &&
a61af66fc99e Initial load
duke
parents:
diff changeset
450 (float)future_unroll_ct > cl->profile_trip_cnt() - 1.0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
451 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
452 }
a61af66fc99e Initial load
duke
parents:
diff changeset
453
a61af66fc99e Initial load
duke
parents:
diff changeset
454 // When unroll count is greater than LoopUnrollMin, don't unroll if:
a61af66fc99e Initial load
duke
parents:
diff changeset
455 // the residual iterations are more than 10% of the trip count
a61af66fc99e Initial load
duke
parents:
diff changeset
456 // and rounds of "unroll,optimize" are not making significant progress
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // Progress defined as current size less than 20% larger than previous size.
a61af66fc99e Initial load
duke
parents:
diff changeset
458 if (UseSuperWord && cl->node_count_before_unroll() > 0 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
459 future_unroll_ct > LoopUnrollMin &&
a61af66fc99e Initial load
duke
parents:
diff changeset
460 (future_unroll_ct - 1) * 10.0 > cl->profile_trip_cnt() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
461 1.2 * cl->node_count_before_unroll() < (double)_body.size()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
462 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
463 }
a61af66fc99e Initial load
duke
parents:
diff changeset
464
a61af66fc99e Initial load
duke
parents:
diff changeset
465 Node *init_n = cl->init_trip();
a61af66fc99e Initial load
duke
parents:
diff changeset
466 Node *limit_n = cl->limit();
a61af66fc99e Initial load
duke
parents:
diff changeset
467 // Non-constant bounds.
a61af66fc99e Initial load
duke
parents:
diff changeset
468 // Protect against over-unrolling when init or/and limit are not constant
a61af66fc99e Initial load
duke
parents:
diff changeset
469 // (so that trip_count's init value is maxint) but iv range is known.
a61af66fc99e Initial load
duke
parents:
diff changeset
470 if( init_n == NULL || !init_n->is_Con() ||
a61af66fc99e Initial load
duke
parents:
diff changeset
471 limit_n == NULL || !limit_n->is_Con() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
472 Node* phi = cl->phi();
a61af66fc99e Initial load
duke
parents:
diff changeset
473 if( phi != NULL ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
474 assert(phi->is_Phi() && phi->in(0) == _head, "Counted loop should have iv phi.");
a61af66fc99e Initial load
duke
parents:
diff changeset
475 const TypeInt* iv_type = phase->_igvn.type(phi)->is_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
476 int next_stride = cl->stride_con() * 2; // stride after this unroll
a61af66fc99e Initial load
duke
parents:
diff changeset
477 if( next_stride > 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
478 if( iv_type->_lo + next_stride <= iv_type->_lo || // overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
479 iv_type->_lo + next_stride > iv_type->_hi ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
480 return false; // over-unrolling
a61af66fc99e Initial load
duke
parents:
diff changeset
481 }
a61af66fc99e Initial load
duke
parents:
diff changeset
482 } else if( next_stride < 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
483 if( iv_type->_hi + next_stride >= iv_type->_hi || // overflow
a61af66fc99e Initial load
duke
parents:
diff changeset
484 iv_type->_hi + next_stride < iv_type->_lo ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 return false; // over-unrolling
a61af66fc99e Initial load
duke
parents:
diff changeset
486 }
a61af66fc99e Initial load
duke
parents:
diff changeset
487 }
a61af66fc99e Initial load
duke
parents:
diff changeset
488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
490
a61af66fc99e Initial load
duke
parents:
diff changeset
491 // Adjust body_size to determine if we unroll or not
a61af66fc99e Initial load
duke
parents:
diff changeset
492 uint body_size = _body.size();
a61af66fc99e Initial load
duke
parents:
diff changeset
493 // Key test to unroll CaffeineMark's Logic test
a61af66fc99e Initial load
duke
parents:
diff changeset
494 int xors_in_loop = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
495 // Also count ModL, DivL and MulL which expand mightly
a61af66fc99e Initial load
duke
parents:
diff changeset
496 for( uint k = 0; k < _body.size(); k++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
497 switch( _body.at(k)->Opcode() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
498 case Op_XorI: xors_in_loop++; break; // CaffeineMark's Logic test
a61af66fc99e Initial load
duke
parents:
diff changeset
499 case Op_ModL: body_size += 30; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
500 case Op_DivL: body_size += 30; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
501 case Op_MulL: body_size += 10; break;
a61af66fc99e Initial load
duke
parents:
diff changeset
502 }
a61af66fc99e Initial load
duke
parents:
diff changeset
503 }
a61af66fc99e Initial load
duke
parents:
diff changeset
504
a61af66fc99e Initial load
duke
parents:
diff changeset
505 // Check for being too big
a61af66fc99e Initial load
duke
parents:
diff changeset
506 if( body_size > (uint)LoopUnrollLimit ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
507 if( xors_in_loop >= 4 && body_size < (uint)LoopUnrollLimit*4) return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
508 // Normal case: loop too big
a61af66fc99e Initial load
duke
parents:
diff changeset
509 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
510 }
a61af66fc99e Initial load
duke
parents:
diff changeset
511
a61af66fc99e Initial load
duke
parents:
diff changeset
512 // Check for stride being a small enough constant
a61af66fc99e Initial load
duke
parents:
diff changeset
513 if( abs(cl->stride_con()) > (1<<3) ) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
514
a61af66fc99e Initial load
duke
parents:
diff changeset
515 // Unroll once! (Each trip will soon do double iterations)
a61af66fc99e Initial load
duke
parents:
diff changeset
516 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
517 }
a61af66fc99e Initial load
duke
parents:
diff changeset
518
a61af66fc99e Initial load
duke
parents:
diff changeset
519 //------------------------------policy_align-----------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
520 // Return TRUE or FALSE if the loop should be cache-line aligned. Gather the
a61af66fc99e Initial load
duke
parents:
diff changeset
521 // expression that does the alignment. Note that only one array base can be
605
98cb887364d3 6810672: Comment typos
twisti
parents: 420
diff changeset
522 // aligned in a loop (unless the VM guarantees mutual alignment). Note that
0
a61af66fc99e Initial load
duke
parents:
diff changeset
523 // if we vectorize short memory ops into longer memory ops, we may want to
a61af66fc99e Initial load
duke
parents:
diff changeset
524 // increase alignment.
a61af66fc99e Initial load
duke
parents:
diff changeset
525 bool IdealLoopTree::policy_align( PhaseIdealLoop *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
526 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
527 }
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529 //------------------------------policy_range_check-----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
530 // Return TRUE or FALSE if the loop should be range-check-eliminated.
a61af66fc99e Initial load
duke
parents:
diff changeset
531 // Actually we do iteration-splitting, a more powerful form of RCE.
a61af66fc99e Initial load
duke
parents:
diff changeset
532 bool IdealLoopTree::policy_range_check( PhaseIdealLoop *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
533 if( !RangeCheckElimination ) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
534
a61af66fc99e Initial load
duke
parents:
diff changeset
535 CountedLoopNode *cl = _head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
536 // If we unrolled with no intention of doing RCE and we later
a61af66fc99e Initial load
duke
parents:
diff changeset
537 // changed our minds, we got no pre-loop. Either we need to
a61af66fc99e Initial load
duke
parents:
diff changeset
538 // make a new pre-loop, or we gotta disallow RCE.
a61af66fc99e Initial load
duke
parents:
diff changeset
539 if( cl->is_main_no_pre_loop() ) return false; // Disallowed for now.
a61af66fc99e Initial load
duke
parents:
diff changeset
540 Node *trip_counter = cl->phi();
a61af66fc99e Initial load
duke
parents:
diff changeset
541
a61af66fc99e Initial load
duke
parents:
diff changeset
542 // Check loop body for tests of trip-counter plus loop-invariant vs
a61af66fc99e Initial load
duke
parents:
diff changeset
543 // loop-invariant.
a61af66fc99e Initial load
duke
parents:
diff changeset
544 for( uint i = 0; i < _body.size(); i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
545 Node *iff = _body[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
546 if( iff->Opcode() == Op_If ) { // Test?
a61af66fc99e Initial load
duke
parents:
diff changeset
547
a61af66fc99e Initial load
duke
parents:
diff changeset
548 // Comparing trip+off vs limit
a61af66fc99e Initial load
duke
parents:
diff changeset
549 Node *bol = iff->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
550 if( bol->req() != 2 ) continue; // dead constant test
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
551 if (!bol->is_Bool()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
552 assert(UseLoopPredicate && bol->Opcode() == Op_Conv2B, "predicate check only");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
553 continue;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
554 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
555 Node *cmp = bol->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
556
a61af66fc99e Initial load
duke
parents:
diff changeset
557 Node *rc_exp = cmp->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
558 Node *limit = cmp->in(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
559
a61af66fc99e Initial load
duke
parents:
diff changeset
560 Node *limit_c = phase->get_ctrl(limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
561 if( limit_c == phase->C->top() )
a61af66fc99e Initial load
duke
parents:
diff changeset
562 return false; // Found dead test on live IF? No RCE!
a61af66fc99e Initial load
duke
parents:
diff changeset
563 if( is_member(phase->get_loop(limit_c) ) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
564 // Compare might have operands swapped; commute them
a61af66fc99e Initial load
duke
parents:
diff changeset
565 rc_exp = cmp->in(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
566 limit = cmp->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
567 limit_c = phase->get_ctrl(limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
568 if( is_member(phase->get_loop(limit_c) ) )
a61af66fc99e Initial load
duke
parents:
diff changeset
569 continue; // Both inputs are loop varying; cannot RCE
a61af66fc99e Initial load
duke
parents:
diff changeset
570 }
a61af66fc99e Initial load
duke
parents:
diff changeset
571
a61af66fc99e Initial load
duke
parents:
diff changeset
572 if (!phase->is_scaled_iv_plus_offset(rc_exp, trip_counter, NULL, NULL)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
573 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
574 }
a61af66fc99e Initial load
duke
parents:
diff changeset
575 // Yeah! Found a test like 'trip+off vs limit'
a61af66fc99e Initial load
duke
parents:
diff changeset
576 // Test is an IfNode, has 2 projections. If BOTH are in the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
577 // we need loop unswitching instead of iteration splitting.
a61af66fc99e Initial load
duke
parents:
diff changeset
578 if( is_loop_exit(iff) )
a61af66fc99e Initial load
duke
parents:
diff changeset
579 return true; // Found reason to split iterations
a61af66fc99e Initial load
duke
parents:
diff changeset
580 } // End of is IF
a61af66fc99e Initial load
duke
parents:
diff changeset
581 }
a61af66fc99e Initial load
duke
parents:
diff changeset
582
a61af66fc99e Initial load
duke
parents:
diff changeset
583 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
584 }
a61af66fc99e Initial load
duke
parents:
diff changeset
585
a61af66fc99e Initial load
duke
parents:
diff changeset
586 //------------------------------policy_peel_only-------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
587 // Return TRUE or FALSE if the loop should NEVER be RCE'd or aligned. Useful
a61af66fc99e Initial load
duke
parents:
diff changeset
588 // for unrolling loops with NO array accesses.
a61af66fc99e Initial load
duke
parents:
diff changeset
589 bool IdealLoopTree::policy_peel_only( PhaseIdealLoop *phase ) const {
a61af66fc99e Initial load
duke
parents:
diff changeset
590
a61af66fc99e Initial load
duke
parents:
diff changeset
591 for( uint i = 0; i < _body.size(); i++ )
a61af66fc99e Initial load
duke
parents:
diff changeset
592 if( _body[i]->is_Mem() )
a61af66fc99e Initial load
duke
parents:
diff changeset
593 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
594
a61af66fc99e Initial load
duke
parents:
diff changeset
595 // No memory accesses at all!
a61af66fc99e Initial load
duke
parents:
diff changeset
596 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
597 }
a61af66fc99e Initial load
duke
parents:
diff changeset
598
a61af66fc99e Initial load
duke
parents:
diff changeset
599 //------------------------------clone_up_backedge_goo--------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
600 // If Node n lives in the back_ctrl block and cannot float, we clone a private
a61af66fc99e Initial load
duke
parents:
diff changeset
601 // version of n in preheader_ctrl block and return that, otherwise return n.
a61af66fc99e Initial load
duke
parents:
diff changeset
602 Node *PhaseIdealLoop::clone_up_backedge_goo( Node *back_ctrl, Node *preheader_ctrl, Node *n ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
603 if( get_ctrl(n) != back_ctrl ) return n;
a61af66fc99e Initial load
duke
parents:
diff changeset
604
a61af66fc99e Initial load
duke
parents:
diff changeset
605 Node *x = NULL; // If required, a clone of 'n'
a61af66fc99e Initial load
duke
parents:
diff changeset
606 // Check for 'n' being pinned in the backedge.
a61af66fc99e Initial load
duke
parents:
diff changeset
607 if( n->in(0) && n->in(0) == back_ctrl ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
608 x = n->clone(); // Clone a copy of 'n' to preheader
a61af66fc99e Initial load
duke
parents:
diff changeset
609 x->set_req( 0, preheader_ctrl ); // Fix x's control input to preheader
a61af66fc99e Initial load
duke
parents:
diff changeset
610 }
a61af66fc99e Initial load
duke
parents:
diff changeset
611
a61af66fc99e Initial load
duke
parents:
diff changeset
612 // Recursive fixup any other input edges into x.
a61af66fc99e Initial load
duke
parents:
diff changeset
613 // If there are no changes we can just return 'n', otherwise
a61af66fc99e Initial load
duke
parents:
diff changeset
614 // we need to clone a private copy and change it.
a61af66fc99e Initial load
duke
parents:
diff changeset
615 for( uint i = 1; i < n->req(); i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
616 Node *g = clone_up_backedge_goo( back_ctrl, preheader_ctrl, n->in(i) );
a61af66fc99e Initial load
duke
parents:
diff changeset
617 if( g != n->in(i) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
618 if( !x )
a61af66fc99e Initial load
duke
parents:
diff changeset
619 x = n->clone();
a61af66fc99e Initial load
duke
parents:
diff changeset
620 x->set_req(i, g);
a61af66fc99e Initial load
duke
parents:
diff changeset
621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
622 }
a61af66fc99e Initial load
duke
parents:
diff changeset
623 if( x ) { // x can legally float to pre-header location
a61af66fc99e Initial load
duke
parents:
diff changeset
624 register_new_node( x, preheader_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
625 return x;
a61af66fc99e Initial load
duke
parents:
diff changeset
626 } else { // raise n to cover LCA of uses
a61af66fc99e Initial load
duke
parents:
diff changeset
627 set_ctrl( n, find_non_split_ctrl(back_ctrl->in(0)) );
a61af66fc99e Initial load
duke
parents:
diff changeset
628 }
a61af66fc99e Initial load
duke
parents:
diff changeset
629 return n;
a61af66fc99e Initial load
duke
parents:
diff changeset
630 }
a61af66fc99e Initial load
duke
parents:
diff changeset
631
a61af66fc99e Initial load
duke
parents:
diff changeset
632 //------------------------------insert_pre_post_loops--------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
633 // Insert pre and post loops. If peel_only is set, the pre-loop can not have
a61af66fc99e Initial load
duke
parents:
diff changeset
634 // more iterations added. It acts as a 'peel' only, no lower-bound RCE, no
a61af66fc99e Initial load
duke
parents:
diff changeset
635 // alignment. Useful to unroll loops that do no array accesses.
a61af66fc99e Initial load
duke
parents:
diff changeset
636 void PhaseIdealLoop::insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
637
a61af66fc99e Initial load
duke
parents:
diff changeset
638 C->set_major_progress();
a61af66fc99e Initial load
duke
parents:
diff changeset
639
a61af66fc99e Initial load
duke
parents:
diff changeset
640 // Find common pieces of the loop being guarded with pre & post loops
a61af66fc99e Initial load
duke
parents:
diff changeset
641 CountedLoopNode *main_head = loop->_head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
642 assert( main_head->is_normal_loop(), "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
643 CountedLoopEndNode *main_end = main_head->loopexit();
a61af66fc99e Initial load
duke
parents:
diff changeset
644 assert( main_end->outcnt() == 2, "1 true, 1 false path only" );
a61af66fc99e Initial load
duke
parents:
diff changeset
645 uint dd_main_head = dom_depth(main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
646 uint max = main_head->outcnt();
a61af66fc99e Initial load
duke
parents:
diff changeset
647
a61af66fc99e Initial load
duke
parents:
diff changeset
648 Node *pre_header= main_head->in(LoopNode::EntryControl);
a61af66fc99e Initial load
duke
parents:
diff changeset
649 Node *init = main_head->init_trip();
a61af66fc99e Initial load
duke
parents:
diff changeset
650 Node *incr = main_end ->incr();
a61af66fc99e Initial load
duke
parents:
diff changeset
651 Node *limit = main_end ->limit();
a61af66fc99e Initial load
duke
parents:
diff changeset
652 Node *stride = main_end ->stride();
a61af66fc99e Initial load
duke
parents:
diff changeset
653 Node *cmp = main_end ->cmp_node();
a61af66fc99e Initial load
duke
parents:
diff changeset
654 BoolTest::mask b_test = main_end->test_trip();
a61af66fc99e Initial load
duke
parents:
diff changeset
655
a61af66fc99e Initial load
duke
parents:
diff changeset
656 // Need only 1 user of 'bol' because I will be hacking the loop bounds.
a61af66fc99e Initial load
duke
parents:
diff changeset
657 Node *bol = main_end->in(CountedLoopEndNode::TestValue);
a61af66fc99e Initial load
duke
parents:
diff changeset
658 if( bol->outcnt() != 1 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
659 bol = bol->clone();
a61af66fc99e Initial load
duke
parents:
diff changeset
660 register_new_node(bol,main_end->in(CountedLoopEndNode::TestControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
661 _igvn.hash_delete(main_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
662 main_end->set_req(CountedLoopEndNode::TestValue, bol);
a61af66fc99e Initial load
duke
parents:
diff changeset
663 }
a61af66fc99e Initial load
duke
parents:
diff changeset
664 // Need only 1 user of 'cmp' because I will be hacking the loop bounds.
a61af66fc99e Initial load
duke
parents:
diff changeset
665 if( cmp->outcnt() != 1 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
666 cmp = cmp->clone();
a61af66fc99e Initial load
duke
parents:
diff changeset
667 register_new_node(cmp,main_end->in(CountedLoopEndNode::TestControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
668 _igvn.hash_delete(bol);
a61af66fc99e Initial load
duke
parents:
diff changeset
669 bol->set_req(1, cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
670 }
a61af66fc99e Initial load
duke
parents:
diff changeset
671
a61af66fc99e Initial load
duke
parents:
diff changeset
672 //------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
673 // Step A: Create Post-Loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
674 Node* main_exit = main_end->proj_out(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
675 assert( main_exit->Opcode() == Op_IfFalse, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
676 int dd_main_exit = dom_depth(main_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
677
a61af66fc99e Initial load
duke
parents:
diff changeset
678 // Step A1: Clone the loop body. The clone becomes the post-loop. The main
a61af66fc99e Initial load
duke
parents:
diff changeset
679 // loop pre-header illegally has 2 control users (old & new loops).
a61af66fc99e Initial load
duke
parents:
diff changeset
680 clone_loop( loop, old_new, dd_main_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
681 assert( old_new[main_end ->_idx]->Opcode() == Op_CountedLoopEnd, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
682 CountedLoopNode *post_head = old_new[main_head->_idx]->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
683 post_head->set_post_loop(main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
684
400
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
685 // Reduce the post-loop trip count.
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
686 CountedLoopEndNode* post_end = old_new[main_end ->_idx]->as_CountedLoopEnd();
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
687 post_end->_prob = PROB_FAIR;
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
688
0
a61af66fc99e Initial load
duke
parents:
diff changeset
689 // Build the main-loop normal exit.
a61af66fc99e Initial load
duke
parents:
diff changeset
690 IfFalseNode *new_main_exit = new (C, 1) IfFalseNode(main_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
691 _igvn.register_new_node_with_optimizer( new_main_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
692 set_idom(new_main_exit, main_end, dd_main_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
693 set_loop(new_main_exit, loop->_parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
694
a61af66fc99e Initial load
duke
parents:
diff changeset
695 // Step A2: Build a zero-trip guard for the post-loop. After leaving the
a61af66fc99e Initial load
duke
parents:
diff changeset
696 // main-loop, the post-loop may not execute at all. We 'opaque' the incr
a61af66fc99e Initial load
duke
parents:
diff changeset
697 // (the main-loop trip-counter exit value) because we will be changing
a61af66fc99e Initial load
duke
parents:
diff changeset
698 // the exit value (via unrolling) so we cannot constant-fold away the zero
a61af66fc99e Initial load
duke
parents:
diff changeset
699 // trip guard until all unrolling is done.
216
8d191a7697e2 6715633: when matching a memory node the adr_type should not change
kvn
parents: 113
diff changeset
700 Node *zer_opaq = new (C, 2) Opaque1Node(C, incr);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
701 Node *zer_cmp = new (C, 3) CmpINode( zer_opaq, limit );
a61af66fc99e Initial load
duke
parents:
diff changeset
702 Node *zer_bol = new (C, 2) BoolNode( zer_cmp, b_test );
a61af66fc99e Initial load
duke
parents:
diff changeset
703 register_new_node( zer_opaq, new_main_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
704 register_new_node( zer_cmp , new_main_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
705 register_new_node( zer_bol , new_main_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
706
a61af66fc99e Initial load
duke
parents:
diff changeset
707 // Build the IfNode
a61af66fc99e Initial load
duke
parents:
diff changeset
708 IfNode *zer_iff = new (C, 2) IfNode( new_main_exit, zer_bol, PROB_FAIR, COUNT_UNKNOWN );
a61af66fc99e Initial load
duke
parents:
diff changeset
709 _igvn.register_new_node_with_optimizer( zer_iff );
a61af66fc99e Initial load
duke
parents:
diff changeset
710 set_idom(zer_iff, new_main_exit, dd_main_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
711 set_loop(zer_iff, loop->_parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
712
a61af66fc99e Initial load
duke
parents:
diff changeset
713 // Plug in the false-path, taken if we need to skip post-loop
a61af66fc99e Initial load
duke
parents:
diff changeset
714 _igvn.hash_delete( main_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
715 main_exit->set_req(0, zer_iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
716 _igvn._worklist.push(main_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
717 set_idom(main_exit, zer_iff, dd_main_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
718 set_idom(main_exit->unique_out(), zer_iff, dd_main_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
719 // Make the true-path, must enter the post loop
a61af66fc99e Initial load
duke
parents:
diff changeset
720 Node *zer_taken = new (C, 1) IfTrueNode( zer_iff );
a61af66fc99e Initial load
duke
parents:
diff changeset
721 _igvn.register_new_node_with_optimizer( zer_taken );
a61af66fc99e Initial load
duke
parents:
diff changeset
722 set_idom(zer_taken, zer_iff, dd_main_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
723 set_loop(zer_taken, loop->_parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
724 // Plug in the true path
a61af66fc99e Initial load
duke
parents:
diff changeset
725 _igvn.hash_delete( post_head );
a61af66fc99e Initial load
duke
parents:
diff changeset
726 post_head->set_req(LoopNode::EntryControl, zer_taken);
a61af66fc99e Initial load
duke
parents:
diff changeset
727 set_idom(post_head, zer_taken, dd_main_exit);
a61af66fc99e Initial load
duke
parents:
diff changeset
728
a61af66fc99e Initial load
duke
parents:
diff changeset
729 // Step A3: Make the fall-in values to the post-loop come from the
a61af66fc99e Initial load
duke
parents:
diff changeset
730 // fall-out values of the main-loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
731 for (DUIterator_Fast imax, i = main_head->fast_outs(imax); i < imax; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
732 Node* main_phi = main_head->fast_out(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
733 if( main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() >0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
734 Node *post_phi = old_new[main_phi->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
735 Node *fallmain = clone_up_backedge_goo(main_head->back_control(),
a61af66fc99e Initial load
duke
parents:
diff changeset
736 post_head->init_control(),
a61af66fc99e Initial load
duke
parents:
diff changeset
737 main_phi->in(LoopNode::LoopBackControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
738 _igvn.hash_delete(post_phi);
a61af66fc99e Initial load
duke
parents:
diff changeset
739 post_phi->set_req( LoopNode::EntryControl, fallmain );
a61af66fc99e Initial load
duke
parents:
diff changeset
740 }
a61af66fc99e Initial load
duke
parents:
diff changeset
741 }
a61af66fc99e Initial load
duke
parents:
diff changeset
742
a61af66fc99e Initial load
duke
parents:
diff changeset
743 // Update local caches for next stanza
a61af66fc99e Initial load
duke
parents:
diff changeset
744 main_exit = new_main_exit;
a61af66fc99e Initial load
duke
parents:
diff changeset
745
a61af66fc99e Initial load
duke
parents:
diff changeset
746
a61af66fc99e Initial load
duke
parents:
diff changeset
747 //------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
748 // Step B: Create Pre-Loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
749
a61af66fc99e Initial load
duke
parents:
diff changeset
750 // Step B1: Clone the loop body. The clone becomes the pre-loop. The main
a61af66fc99e Initial load
duke
parents:
diff changeset
751 // loop pre-header illegally has 2 control users (old & new loops).
a61af66fc99e Initial load
duke
parents:
diff changeset
752 clone_loop( loop, old_new, dd_main_head );
a61af66fc99e Initial load
duke
parents:
diff changeset
753 CountedLoopNode* pre_head = old_new[main_head->_idx]->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
754 CountedLoopEndNode* pre_end = old_new[main_end ->_idx]->as_CountedLoopEnd();
a61af66fc99e Initial load
duke
parents:
diff changeset
755 pre_head->set_pre_loop(main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
756 Node *pre_incr = old_new[incr->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
757
400
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
758 // Reduce the pre-loop trip count.
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
759 pre_end->_prob = PROB_FAIR;
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
760
0
a61af66fc99e Initial load
duke
parents:
diff changeset
761 // Find the pre-loop normal exit.
a61af66fc99e Initial load
duke
parents:
diff changeset
762 Node* pre_exit = pre_end->proj_out(false);
a61af66fc99e Initial load
duke
parents:
diff changeset
763 assert( pre_exit->Opcode() == Op_IfFalse, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
764 IfFalseNode *new_pre_exit = new (C, 1) IfFalseNode(pre_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
765 _igvn.register_new_node_with_optimizer( new_pre_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
766 set_idom(new_pre_exit, pre_end, dd_main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
767 set_loop(new_pre_exit, loop->_parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
768
a61af66fc99e Initial load
duke
parents:
diff changeset
769 // Step B2: Build a zero-trip guard for the main-loop. After leaving the
a61af66fc99e Initial load
duke
parents:
diff changeset
770 // pre-loop, the main-loop may not execute at all. Later in life this
a61af66fc99e Initial load
duke
parents:
diff changeset
771 // zero-trip guard will become the minimum-trip guard when we unroll
a61af66fc99e Initial load
duke
parents:
diff changeset
772 // the main-loop.
216
8d191a7697e2 6715633: when matching a memory node the adr_type should not change
kvn
parents: 113
diff changeset
773 Node *min_opaq = new (C, 2) Opaque1Node(C, limit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
774 Node *min_cmp = new (C, 3) CmpINode( pre_incr, min_opaq );
a61af66fc99e Initial load
duke
parents:
diff changeset
775 Node *min_bol = new (C, 2) BoolNode( min_cmp, b_test );
a61af66fc99e Initial load
duke
parents:
diff changeset
776 register_new_node( min_opaq, new_pre_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
777 register_new_node( min_cmp , new_pre_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
778 register_new_node( min_bol , new_pre_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
779
400
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
780 // Build the IfNode (assume the main-loop is executed always).
cc80376deb0c 6667595: Set probability FAIR for pre-, post- loops and ALWAYS for main loop
kvn
parents: 367
diff changeset
781 IfNode *min_iff = new (C, 2) IfNode( new_pre_exit, min_bol, PROB_ALWAYS, COUNT_UNKNOWN );
0
a61af66fc99e Initial load
duke
parents:
diff changeset
782 _igvn.register_new_node_with_optimizer( min_iff );
a61af66fc99e Initial load
duke
parents:
diff changeset
783 set_idom(min_iff, new_pre_exit, dd_main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
784 set_loop(min_iff, loop->_parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
785
a61af66fc99e Initial load
duke
parents:
diff changeset
786 // Plug in the false-path, taken if we need to skip main-loop
a61af66fc99e Initial load
duke
parents:
diff changeset
787 _igvn.hash_delete( pre_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
788 pre_exit->set_req(0, min_iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
789 set_idom(pre_exit, min_iff, dd_main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
790 set_idom(pre_exit->unique_out(), min_iff, dd_main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
791 // Make the true-path, must enter the main loop
a61af66fc99e Initial load
duke
parents:
diff changeset
792 Node *min_taken = new (C, 1) IfTrueNode( min_iff );
a61af66fc99e Initial load
duke
parents:
diff changeset
793 _igvn.register_new_node_with_optimizer( min_taken );
a61af66fc99e Initial load
duke
parents:
diff changeset
794 set_idom(min_taken, min_iff, dd_main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
795 set_loop(min_taken, loop->_parent);
a61af66fc99e Initial load
duke
parents:
diff changeset
796 // Plug in the true path
a61af66fc99e Initial load
duke
parents:
diff changeset
797 _igvn.hash_delete( main_head );
a61af66fc99e Initial load
duke
parents:
diff changeset
798 main_head->set_req(LoopNode::EntryControl, min_taken);
a61af66fc99e Initial load
duke
parents:
diff changeset
799 set_idom(main_head, min_taken, dd_main_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
800
a61af66fc99e Initial load
duke
parents:
diff changeset
801 // Step B3: Make the fall-in values to the main-loop come from the
a61af66fc99e Initial load
duke
parents:
diff changeset
802 // fall-out values of the pre-loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
803 for (DUIterator_Fast i2max, i2 = main_head->fast_outs(i2max); i2 < i2max; i2++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
804 Node* main_phi = main_head->fast_out(i2);
a61af66fc99e Initial load
duke
parents:
diff changeset
805 if( main_phi->is_Phi() && main_phi->in(0) == main_head && main_phi->outcnt() > 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
806 Node *pre_phi = old_new[main_phi->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
807 Node *fallpre = clone_up_backedge_goo(pre_head->back_control(),
a61af66fc99e Initial load
duke
parents:
diff changeset
808 main_head->init_control(),
a61af66fc99e Initial load
duke
parents:
diff changeset
809 pre_phi->in(LoopNode::LoopBackControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
810 _igvn.hash_delete(main_phi);
a61af66fc99e Initial load
duke
parents:
diff changeset
811 main_phi->set_req( LoopNode::EntryControl, fallpre );
a61af66fc99e Initial load
duke
parents:
diff changeset
812 }
a61af66fc99e Initial load
duke
parents:
diff changeset
813 }
a61af66fc99e Initial load
duke
parents:
diff changeset
814
a61af66fc99e Initial load
duke
parents:
diff changeset
815 // Step B4: Shorten the pre-loop to run only 1 iteration (for now).
a61af66fc99e Initial load
duke
parents:
diff changeset
816 // RCE and alignment may change this later.
a61af66fc99e Initial load
duke
parents:
diff changeset
817 Node *cmp_end = pre_end->cmp_node();
a61af66fc99e Initial load
duke
parents:
diff changeset
818 assert( cmp_end->in(2) == limit, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
819 Node *pre_limit = new (C, 3) AddINode( init, stride );
a61af66fc99e Initial load
duke
parents:
diff changeset
820
a61af66fc99e Initial load
duke
parents:
diff changeset
821 // Save the original loop limit in this Opaque1 node for
a61af66fc99e Initial load
duke
parents:
diff changeset
822 // use by range check elimination.
216
8d191a7697e2 6715633: when matching a memory node the adr_type should not change
kvn
parents: 113
diff changeset
823 Node *pre_opaq = new (C, 3) Opaque1Node(C, pre_limit, limit);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
824
a61af66fc99e Initial load
duke
parents:
diff changeset
825 register_new_node( pre_limit, pre_head->in(0) );
a61af66fc99e Initial load
duke
parents:
diff changeset
826 register_new_node( pre_opaq , pre_head->in(0) );
a61af66fc99e Initial load
duke
parents:
diff changeset
827
a61af66fc99e Initial load
duke
parents:
diff changeset
828 // Since no other users of pre-loop compare, I can hack limit directly
a61af66fc99e Initial load
duke
parents:
diff changeset
829 assert( cmp_end->outcnt() == 1, "no other users" );
a61af66fc99e Initial load
duke
parents:
diff changeset
830 _igvn.hash_delete(cmp_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
831 cmp_end->set_req(2, peel_only ? pre_limit : pre_opaq);
a61af66fc99e Initial load
duke
parents:
diff changeset
832
a61af66fc99e Initial load
duke
parents:
diff changeset
833 // Special case for not-equal loop bounds:
a61af66fc99e Initial load
duke
parents:
diff changeset
834 // Change pre loop test, main loop test, and the
a61af66fc99e Initial load
duke
parents:
diff changeset
835 // main loop guard test to use lt or gt depending on stride
a61af66fc99e Initial load
duke
parents:
diff changeset
836 // direction:
a61af66fc99e Initial load
duke
parents:
diff changeset
837 // positive stride use <
a61af66fc99e Initial load
duke
parents:
diff changeset
838 // negative stride use >
a61af66fc99e Initial load
duke
parents:
diff changeset
839
a61af66fc99e Initial load
duke
parents:
diff changeset
840 if (pre_end->in(CountedLoopEndNode::TestValue)->as_Bool()->_test._test == BoolTest::ne) {
a61af66fc99e Initial load
duke
parents:
diff changeset
841
a61af66fc99e Initial load
duke
parents:
diff changeset
842 BoolTest::mask new_test = (main_end->stride_con() > 0) ? BoolTest::lt : BoolTest::gt;
a61af66fc99e Initial load
duke
parents:
diff changeset
843 // Modify pre loop end condition
a61af66fc99e Initial load
duke
parents:
diff changeset
844 Node* pre_bol = pre_end->in(CountedLoopEndNode::TestValue)->as_Bool();
a61af66fc99e Initial load
duke
parents:
diff changeset
845 BoolNode* new_bol0 = new (C, 2) BoolNode(pre_bol->in(1), new_test);
a61af66fc99e Initial load
duke
parents:
diff changeset
846 register_new_node( new_bol0, pre_head->in(0) );
a61af66fc99e Initial load
duke
parents:
diff changeset
847 _igvn.hash_delete(pre_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
848 pre_end->set_req(CountedLoopEndNode::TestValue, new_bol0);
a61af66fc99e Initial load
duke
parents:
diff changeset
849 // Modify main loop guard condition
a61af66fc99e Initial load
duke
parents:
diff changeset
850 assert(min_iff->in(CountedLoopEndNode::TestValue) == min_bol, "guard okay");
a61af66fc99e Initial load
duke
parents:
diff changeset
851 BoolNode* new_bol1 = new (C, 2) BoolNode(min_bol->in(1), new_test);
a61af66fc99e Initial load
duke
parents:
diff changeset
852 register_new_node( new_bol1, new_pre_exit );
a61af66fc99e Initial load
duke
parents:
diff changeset
853 _igvn.hash_delete(min_iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
854 min_iff->set_req(CountedLoopEndNode::TestValue, new_bol1);
a61af66fc99e Initial load
duke
parents:
diff changeset
855 // Modify main loop end condition
a61af66fc99e Initial load
duke
parents:
diff changeset
856 BoolNode* main_bol = main_end->in(CountedLoopEndNode::TestValue)->as_Bool();
a61af66fc99e Initial load
duke
parents:
diff changeset
857 BoolNode* new_bol2 = new (C, 2) BoolNode(main_bol->in(1), new_test);
a61af66fc99e Initial load
duke
parents:
diff changeset
858 register_new_node( new_bol2, main_end->in(CountedLoopEndNode::TestControl) );
a61af66fc99e Initial load
duke
parents:
diff changeset
859 _igvn.hash_delete(main_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
860 main_end->set_req(CountedLoopEndNode::TestValue, new_bol2);
a61af66fc99e Initial load
duke
parents:
diff changeset
861 }
a61af66fc99e Initial load
duke
parents:
diff changeset
862
a61af66fc99e Initial load
duke
parents:
diff changeset
863 // Flag main loop
a61af66fc99e Initial load
duke
parents:
diff changeset
864 main_head->set_main_loop();
a61af66fc99e Initial load
duke
parents:
diff changeset
865 if( peel_only ) main_head->set_main_no_pre_loop();
a61af66fc99e Initial load
duke
parents:
diff changeset
866
a61af66fc99e Initial load
duke
parents:
diff changeset
867 // It's difficult to be precise about the trip-counts
a61af66fc99e Initial load
duke
parents:
diff changeset
868 // for the pre/post loops. They are usually very short,
a61af66fc99e Initial load
duke
parents:
diff changeset
869 // so guess that 4 trips is a reasonable value.
a61af66fc99e Initial load
duke
parents:
diff changeset
870 post_head->set_profile_trip_cnt(4.0);
a61af66fc99e Initial load
duke
parents:
diff changeset
871 pre_head->set_profile_trip_cnt(4.0);
a61af66fc99e Initial load
duke
parents:
diff changeset
872
a61af66fc99e Initial load
duke
parents:
diff changeset
873 // Now force out all loop-invariant dominating tests. The optimizer
a61af66fc99e Initial load
duke
parents:
diff changeset
874 // finds some, but we _know_ they are all useless.
a61af66fc99e Initial load
duke
parents:
diff changeset
875 peeled_dom_test_elim(loop,old_new);
a61af66fc99e Initial load
duke
parents:
diff changeset
876 }
a61af66fc99e Initial load
duke
parents:
diff changeset
877
a61af66fc99e Initial load
duke
parents:
diff changeset
878 //------------------------------is_invariant-----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
879 // Return true if n is invariant
a61af66fc99e Initial load
duke
parents:
diff changeset
880 bool IdealLoopTree::is_invariant(Node* n) const {
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
881 Node *n_c = _phase->has_ctrl(n) ? _phase->get_ctrl(n) : n;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
882 if (n_c->is_top()) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
883 return !is_member(_phase->get_loop(n_c));
a61af66fc99e Initial load
duke
parents:
diff changeset
884 }
a61af66fc99e Initial load
duke
parents:
diff changeset
885
a61af66fc99e Initial load
duke
parents:
diff changeset
886
a61af66fc99e Initial load
duke
parents:
diff changeset
887 //------------------------------do_unroll--------------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
888 // Unroll the loop body one step - make each trip do 2 iterations.
a61af66fc99e Initial load
duke
parents:
diff changeset
889 void PhaseIdealLoop::do_unroll( IdealLoopTree *loop, Node_List &old_new, bool adjust_min_trip ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
890 assert( LoopUnrollLimit, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
891 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
892 if( PrintOpto && VerifyLoopOptimizations ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
893 tty->print("Unrolling ");
a61af66fc99e Initial load
duke
parents:
diff changeset
894 loop->dump_head();
a61af66fc99e Initial load
duke
parents:
diff changeset
895 }
a61af66fc99e Initial load
duke
parents:
diff changeset
896 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
897 CountedLoopNode *loop_head = loop->_head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
898 CountedLoopEndNode *loop_end = loop_head->loopexit();
a61af66fc99e Initial load
duke
parents:
diff changeset
899 assert( loop_end, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
900
a61af66fc99e Initial load
duke
parents:
diff changeset
901 // Remember loop node count before unrolling to detect
a61af66fc99e Initial load
duke
parents:
diff changeset
902 // if rounds of unroll,optimize are making progress
a61af66fc99e Initial load
duke
parents:
diff changeset
903 loop_head->set_node_count_before_unroll(loop->_body.size());
a61af66fc99e Initial load
duke
parents:
diff changeset
904
a61af66fc99e Initial load
duke
parents:
diff changeset
905 Node *ctrl = loop_head->in(LoopNode::EntryControl);
a61af66fc99e Initial load
duke
parents:
diff changeset
906 Node *limit = loop_head->limit();
a61af66fc99e Initial load
duke
parents:
diff changeset
907 Node *init = loop_head->init_trip();
a61af66fc99e Initial load
duke
parents:
diff changeset
908 Node *strid = loop_head->stride();
a61af66fc99e Initial load
duke
parents:
diff changeset
909
a61af66fc99e Initial load
duke
parents:
diff changeset
910 Node *opaq = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
911 if( adjust_min_trip ) { // If not maximally unrolling, need adjustment
a61af66fc99e Initial load
duke
parents:
diff changeset
912 assert( loop_head->is_main_loop(), "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
913 assert( ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
914 Node *iff = ctrl->in(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
915 assert( iff->Opcode() == Op_If, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
916 Node *bol = iff->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
917 assert( bol->Opcode() == Op_Bool, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
918 Node *cmp = bol->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
919 assert( cmp->Opcode() == Op_CmpI, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
920 opaq = cmp->in(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
921 // Occasionally it's possible for a pre-loop Opaque1 node to be
a61af66fc99e Initial load
duke
parents:
diff changeset
922 // optimized away and then another round of loop opts attempted.
a61af66fc99e Initial load
duke
parents:
diff changeset
923 // We can not optimize this particular loop in that case.
a61af66fc99e Initial load
duke
parents:
diff changeset
924 if( opaq->Opcode() != Op_Opaque1 )
a61af66fc99e Initial load
duke
parents:
diff changeset
925 return; // Cannot find pre-loop! Bail out!
a61af66fc99e Initial load
duke
parents:
diff changeset
926 }
a61af66fc99e Initial load
duke
parents:
diff changeset
927
a61af66fc99e Initial load
duke
parents:
diff changeset
928 C->set_major_progress();
a61af66fc99e Initial load
duke
parents:
diff changeset
929
a61af66fc99e Initial load
duke
parents:
diff changeset
930 // Adjust max trip count. The trip count is intentionally rounded
a61af66fc99e Initial load
duke
parents:
diff changeset
931 // down here (e.g. 15-> 7-> 3-> 1) because if we unwittingly over-unroll,
a61af66fc99e Initial load
duke
parents:
diff changeset
932 // the main, unrolled, part of the loop will never execute as it is protected
a61af66fc99e Initial load
duke
parents:
diff changeset
933 // by the min-trip test. See bug 4834191 for a case where we over-unrolled
a61af66fc99e Initial load
duke
parents:
diff changeset
934 // and later determined that part of the unrolled loop was dead.
a61af66fc99e Initial load
duke
parents:
diff changeset
935 loop_head->set_trip_count(loop_head->trip_count() / 2);
a61af66fc99e Initial load
duke
parents:
diff changeset
936
a61af66fc99e Initial load
duke
parents:
diff changeset
937 // Double the count of original iterations in the unrolled loop body.
a61af66fc99e Initial load
duke
parents:
diff changeset
938 loop_head->double_unrolled_count();
a61af66fc99e Initial load
duke
parents:
diff changeset
939
a61af66fc99e Initial load
duke
parents:
diff changeset
940 // -----------
a61af66fc99e Initial load
duke
parents:
diff changeset
941 // Step 2: Cut back the trip counter for an unroll amount of 2.
a61af66fc99e Initial load
duke
parents:
diff changeset
942 // Loop will normally trip (limit - init)/stride_con. Since it's a
a61af66fc99e Initial load
duke
parents:
diff changeset
943 // CountedLoop this is exact (stride divides limit-init exactly).
a61af66fc99e Initial load
duke
parents:
diff changeset
944 // We are going to double the loop body, so we want to knock off any
a61af66fc99e Initial load
duke
parents:
diff changeset
945 // odd iteration: (trip_cnt & ~1). Then back compute a new limit.
a61af66fc99e Initial load
duke
parents:
diff changeset
946 Node *span = new (C, 3) SubINode( limit, init );
a61af66fc99e Initial load
duke
parents:
diff changeset
947 register_new_node( span, ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
948 Node *trip = new (C, 3) DivINode( 0, span, strid );
a61af66fc99e Initial load
duke
parents:
diff changeset
949 register_new_node( trip, ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
950 Node *mtwo = _igvn.intcon(-2);
a61af66fc99e Initial load
duke
parents:
diff changeset
951 set_ctrl(mtwo, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
952 Node *rond = new (C, 3) AndINode( trip, mtwo );
a61af66fc99e Initial load
duke
parents:
diff changeset
953 register_new_node( rond, ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
954 Node *spn2 = new (C, 3) MulINode( rond, strid );
a61af66fc99e Initial load
duke
parents:
diff changeset
955 register_new_node( spn2, ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
956 Node *lim2 = new (C, 3) AddINode( spn2, init );
a61af66fc99e Initial load
duke
parents:
diff changeset
957 register_new_node( lim2, ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
958
a61af66fc99e Initial load
duke
parents:
diff changeset
959 // Hammer in the new limit
a61af66fc99e Initial load
duke
parents:
diff changeset
960 Node *ctrl2 = loop_end->in(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
961 Node *cmp2 = new (C, 3) CmpINode( loop_head->incr(), lim2 );
a61af66fc99e Initial load
duke
parents:
diff changeset
962 register_new_node( cmp2, ctrl2 );
a61af66fc99e Initial load
duke
parents:
diff changeset
963 Node *bol2 = new (C, 2) BoolNode( cmp2, loop_end->test_trip() );
a61af66fc99e Initial load
duke
parents:
diff changeset
964 register_new_node( bol2, ctrl2 );
a61af66fc99e Initial load
duke
parents:
diff changeset
965 _igvn.hash_delete(loop_end);
a61af66fc99e Initial load
duke
parents:
diff changeset
966 loop_end->set_req(CountedLoopEndNode::TestValue, bol2);
a61af66fc99e Initial load
duke
parents:
diff changeset
967
a61af66fc99e Initial load
duke
parents:
diff changeset
968 // Step 3: Find the min-trip test guaranteed before a 'main' loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
969 // Make it a 1-trip test (means at least 2 trips).
a61af66fc99e Initial load
duke
parents:
diff changeset
970 if( adjust_min_trip ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
971 // Guard test uses an 'opaque' node which is not shared. Hence I
a61af66fc99e Initial load
duke
parents:
diff changeset
972 // can edit it's inputs directly. Hammer in the new limit for the
a61af66fc99e Initial load
duke
parents:
diff changeset
973 // minimum-trip guard.
a61af66fc99e Initial load
duke
parents:
diff changeset
974 assert( opaq->outcnt() == 1, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
975 _igvn.hash_delete(opaq);
a61af66fc99e Initial load
duke
parents:
diff changeset
976 opaq->set_req(1, lim2);
a61af66fc99e Initial load
duke
parents:
diff changeset
977 }
a61af66fc99e Initial load
duke
parents:
diff changeset
978
a61af66fc99e Initial load
duke
parents:
diff changeset
979 // ---------
a61af66fc99e Initial load
duke
parents:
diff changeset
980 // Step 4: Clone the loop body. Move it inside the loop. This loop body
a61af66fc99e Initial load
duke
parents:
diff changeset
981 // represents the odd iterations; since the loop trips an even number of
a61af66fc99e Initial load
duke
parents:
diff changeset
982 // times its backedge is never taken. Kill the backedge.
a61af66fc99e Initial load
duke
parents:
diff changeset
983 uint dd = dom_depth(loop_head);
a61af66fc99e Initial load
duke
parents:
diff changeset
984 clone_loop( loop, old_new, dd );
a61af66fc99e Initial load
duke
parents:
diff changeset
985
a61af66fc99e Initial load
duke
parents:
diff changeset
986 // Make backedges of the clone equal to backedges of the original.
a61af66fc99e Initial load
duke
parents:
diff changeset
987 // Make the fall-in from the original come from the fall-out of the clone.
a61af66fc99e Initial load
duke
parents:
diff changeset
988 for (DUIterator_Fast jmax, j = loop_head->fast_outs(jmax); j < jmax; j++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
989 Node* phi = loop_head->fast_out(j);
a61af66fc99e Initial load
duke
parents:
diff changeset
990 if( phi->is_Phi() && phi->in(0) == loop_head && phi->outcnt() > 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
991 Node *newphi = old_new[phi->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
992 _igvn.hash_delete( phi );
a61af66fc99e Initial load
duke
parents:
diff changeset
993 _igvn.hash_delete( newphi );
a61af66fc99e Initial load
duke
parents:
diff changeset
994
a61af66fc99e Initial load
duke
parents:
diff changeset
995 phi ->set_req(LoopNode:: EntryControl, newphi->in(LoopNode::LoopBackControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
996 newphi->set_req(LoopNode::LoopBackControl, phi ->in(LoopNode::LoopBackControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
997 phi ->set_req(LoopNode::LoopBackControl, C->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
998 }
a61af66fc99e Initial load
duke
parents:
diff changeset
999 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1000 Node *clone_head = old_new[loop_head->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
1001 _igvn.hash_delete( clone_head );
a61af66fc99e Initial load
duke
parents:
diff changeset
1002 loop_head ->set_req(LoopNode:: EntryControl, clone_head->in(LoopNode::LoopBackControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
1003 clone_head->set_req(LoopNode::LoopBackControl, loop_head ->in(LoopNode::LoopBackControl));
a61af66fc99e Initial load
duke
parents:
diff changeset
1004 loop_head ->set_req(LoopNode::LoopBackControl, C->top());
a61af66fc99e Initial load
duke
parents:
diff changeset
1005 loop->_head = clone_head; // New loop header
a61af66fc99e Initial load
duke
parents:
diff changeset
1006
a61af66fc99e Initial load
duke
parents:
diff changeset
1007 set_idom(loop_head, loop_head ->in(LoopNode::EntryControl), dd);
a61af66fc99e Initial load
duke
parents:
diff changeset
1008 set_idom(clone_head, clone_head->in(LoopNode::EntryControl), dd);
a61af66fc99e Initial load
duke
parents:
diff changeset
1009
a61af66fc99e Initial load
duke
parents:
diff changeset
1010 // Kill the clone's backedge
a61af66fc99e Initial load
duke
parents:
diff changeset
1011 Node *newcle = old_new[loop_end->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
1012 _igvn.hash_delete( newcle );
a61af66fc99e Initial load
duke
parents:
diff changeset
1013 Node *one = _igvn.intcon(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1014 set_ctrl(one, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1015 newcle->set_req(1, one);
a61af66fc99e Initial load
duke
parents:
diff changeset
1016 // Force clone into same loop body
a61af66fc99e Initial load
duke
parents:
diff changeset
1017 uint max = loop->_body.size();
a61af66fc99e Initial load
duke
parents:
diff changeset
1018 for( uint k = 0; k < max; k++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1019 Node *old = loop->_body.at(k);
a61af66fc99e Initial load
duke
parents:
diff changeset
1020 Node *nnn = old_new[old->_idx];
a61af66fc99e Initial load
duke
parents:
diff changeset
1021 loop->_body.push(nnn);
a61af66fc99e Initial load
duke
parents:
diff changeset
1022 if (!has_ctrl(old))
a61af66fc99e Initial load
duke
parents:
diff changeset
1023 set_loop(nnn, loop);
a61af66fc99e Initial load
duke
parents:
diff changeset
1024 }
367
194b8e3a2fc4 6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents: 235
diff changeset
1025
194b8e3a2fc4 6384206: Phis which are later unneeded are impairing our ability to inline based on static types
never
parents: 235
diff changeset
1026 loop->record_for_igvn();
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1027 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1028
a61af66fc99e Initial load
duke
parents:
diff changeset
1029 //------------------------------do_maximally_unroll----------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1030
a61af66fc99e Initial load
duke
parents:
diff changeset
1031 void PhaseIdealLoop::do_maximally_unroll( IdealLoopTree *loop, Node_List &old_new ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1032 CountedLoopNode *cl = loop->_head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1033 assert( cl->trip_count() > 0, "");
a61af66fc99e Initial load
duke
parents:
diff changeset
1034
a61af66fc99e Initial load
duke
parents:
diff changeset
1035 // If loop is tripping an odd number of times, peel odd iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1036 if( (cl->trip_count() & 1) == 1 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1037 do_peeling( loop, old_new );
a61af66fc99e Initial load
duke
parents:
diff changeset
1038 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1039
a61af66fc99e Initial load
duke
parents:
diff changeset
1040 // Now its tripping an even number of times remaining. Double loop body.
a61af66fc99e Initial load
duke
parents:
diff changeset
1041 // Do not adjust pre-guards; they are not needed and do not exist.
a61af66fc99e Initial load
duke
parents:
diff changeset
1042 if( cl->trip_count() > 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1043 do_unroll( loop, old_new, false );
a61af66fc99e Initial load
duke
parents:
diff changeset
1044 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1045 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1046
a61af66fc99e Initial load
duke
parents:
diff changeset
1047 //------------------------------dominates_backedge---------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1048 // Returns true if ctrl is executed on every complete iteration
a61af66fc99e Initial load
duke
parents:
diff changeset
1049 bool IdealLoopTree::dominates_backedge(Node* ctrl) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1050 assert(ctrl->is_CFG(), "must be control");
a61af66fc99e Initial load
duke
parents:
diff changeset
1051 Node* backedge = _head->as_Loop()->in(LoopNode::LoopBackControl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1052 return _phase->dom_lca_internal(ctrl, backedge) == ctrl;
a61af66fc99e Initial load
duke
parents:
diff changeset
1053 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1054
a61af66fc99e Initial load
duke
parents:
diff changeset
1055 //------------------------------add_constraint---------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1056 // Constrain the main loop iterations so the condition:
a61af66fc99e Initial load
duke
parents:
diff changeset
1057 // scale_con * I + offset < limit
a61af66fc99e Initial load
duke
parents:
diff changeset
1058 // always holds true. That is, either increase the number of iterations in
a61af66fc99e Initial load
duke
parents:
diff changeset
1059 // the pre-loop or the post-loop until the condition holds true in the main
a61af66fc99e Initial load
duke
parents:
diff changeset
1060 // loop. Stride, scale, offset and limit are all loop invariant. Further,
a61af66fc99e Initial load
duke
parents:
diff changeset
1061 // stride and scale are constants (offset and limit often are).
a61af66fc99e Initial load
duke
parents:
diff changeset
1062 void PhaseIdealLoop::add_constraint( int stride_con, int scale_con, Node *offset, Node *limit, Node *pre_ctrl, Node **pre_limit, Node **main_limit ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1063
a61af66fc99e Initial load
duke
parents:
diff changeset
1064 // Compute "I :: (limit-offset)/scale_con"
a61af66fc99e Initial load
duke
parents:
diff changeset
1065 Node *con = new (C, 3) SubINode( limit, offset );
a61af66fc99e Initial load
duke
parents:
diff changeset
1066 register_new_node( con, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1067 Node *scale = _igvn.intcon(scale_con);
a61af66fc99e Initial load
duke
parents:
diff changeset
1068 set_ctrl(scale, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1069 Node *X = new (C, 3) DivINode( 0, con, scale );
a61af66fc99e Initial load
duke
parents:
diff changeset
1070 register_new_node( X, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1071
a61af66fc99e Initial load
duke
parents:
diff changeset
1072 // For positive stride, the pre-loop limit always uses a MAX function
a61af66fc99e Initial load
duke
parents:
diff changeset
1073 // and the main loop a MIN function. For negative stride these are
a61af66fc99e Initial load
duke
parents:
diff changeset
1074 // reversed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1075
a61af66fc99e Initial load
duke
parents:
diff changeset
1076 // Also for positive stride*scale the affine function is increasing, so the
a61af66fc99e Initial load
duke
parents:
diff changeset
1077 // pre-loop must check for underflow and the post-loop for overflow.
a61af66fc99e Initial load
duke
parents:
diff changeset
1078 // Negative stride*scale reverses this; pre-loop checks for overflow and
a61af66fc99e Initial load
duke
parents:
diff changeset
1079 // post-loop for underflow.
a61af66fc99e Initial load
duke
parents:
diff changeset
1080 if( stride_con*scale_con > 0 ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1081 // Compute I < (limit-offset)/scale_con
a61af66fc99e Initial load
duke
parents:
diff changeset
1082 // Adjust main-loop last iteration to be MIN/MAX(main_loop,X)
a61af66fc99e Initial load
duke
parents:
diff changeset
1083 *main_limit = (stride_con > 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
1084 ? (Node*)(new (C, 3) MinINode( *main_limit, X ))
a61af66fc99e Initial load
duke
parents:
diff changeset
1085 : (Node*)(new (C, 3) MaxINode( *main_limit, X ));
a61af66fc99e Initial load
duke
parents:
diff changeset
1086 register_new_node( *main_limit, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1087
a61af66fc99e Initial load
duke
parents:
diff changeset
1088 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1089 // Compute (limit-offset)/scale_con + SGN(-scale_con) <= I
a61af66fc99e Initial load
duke
parents:
diff changeset
1090 // Add the negation of the main-loop constraint to the pre-loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
1091 // See footnote [++] below for a derivation of the limit expression.
a61af66fc99e Initial load
duke
parents:
diff changeset
1092 Node *incr = _igvn.intcon(scale_con > 0 ? -1 : 1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1093 set_ctrl(incr, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1094 Node *adj = new (C, 3) AddINode( X, incr );
a61af66fc99e Initial load
duke
parents:
diff changeset
1095 register_new_node( adj, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1096 *pre_limit = (scale_con > 0)
a61af66fc99e Initial load
duke
parents:
diff changeset
1097 ? (Node*)new (C, 3) MinINode( *pre_limit, adj )
a61af66fc99e Initial load
duke
parents:
diff changeset
1098 : (Node*)new (C, 3) MaxINode( *pre_limit, adj );
a61af66fc99e Initial load
duke
parents:
diff changeset
1099 register_new_node( *pre_limit, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1100
a61af66fc99e Initial load
duke
parents:
diff changeset
1101 // [++] Here's the algebra that justifies the pre-loop limit expression:
a61af66fc99e Initial load
duke
parents:
diff changeset
1102 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1103 // NOT( scale_con * I + offset < limit )
a61af66fc99e Initial load
duke
parents:
diff changeset
1104 // ==
a61af66fc99e Initial load
duke
parents:
diff changeset
1105 // scale_con * I + offset >= limit
a61af66fc99e Initial load
duke
parents:
diff changeset
1106 // ==
a61af66fc99e Initial load
duke
parents:
diff changeset
1107 // SGN(scale_con) * I >= (limit-offset)/|scale_con|
a61af66fc99e Initial load
duke
parents:
diff changeset
1108 // ==
a61af66fc99e Initial load
duke
parents:
diff changeset
1109 // (limit-offset)/|scale_con| <= I * SGN(scale_con)
a61af66fc99e Initial load
duke
parents:
diff changeset
1110 // ==
a61af66fc99e Initial load
duke
parents:
diff changeset
1111 // (limit-offset)/|scale_con|-1 < I * SGN(scale_con)
a61af66fc99e Initial load
duke
parents:
diff changeset
1112 // ==
a61af66fc99e Initial load
duke
parents:
diff changeset
1113 // ( if (scale_con > 0) /*common case*/
a61af66fc99e Initial load
duke
parents:
diff changeset
1114 // (limit-offset)/scale_con - 1 < I
a61af66fc99e Initial load
duke
parents:
diff changeset
1115 // else
a61af66fc99e Initial load
duke
parents:
diff changeset
1116 // (limit-offset)/scale_con + 1 > I
a61af66fc99e Initial load
duke
parents:
diff changeset
1117 // )
a61af66fc99e Initial load
duke
parents:
diff changeset
1118 // ( if (scale_con > 0) /*common case*/
a61af66fc99e Initial load
duke
parents:
diff changeset
1119 // (limit-offset)/scale_con + SGN(-scale_con) < I
a61af66fc99e Initial load
duke
parents:
diff changeset
1120 // else
a61af66fc99e Initial load
duke
parents:
diff changeset
1121 // (limit-offset)/scale_con + SGN(-scale_con) > I
a61af66fc99e Initial load
duke
parents:
diff changeset
1122 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1124
a61af66fc99e Initial load
duke
parents:
diff changeset
1125
a61af66fc99e Initial load
duke
parents:
diff changeset
1126 //------------------------------is_scaled_iv---------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1127 // Return true if exp is a constant times an induction var
a61af66fc99e Initial load
duke
parents:
diff changeset
1128 bool PhaseIdealLoop::is_scaled_iv(Node* exp, Node* iv, int* p_scale) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1129 if (exp == iv) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1130 if (p_scale != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1131 *p_scale = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1132 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1133 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1134 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1135 int opc = exp->Opcode();
a61af66fc99e Initial load
duke
parents:
diff changeset
1136 if (opc == Op_MulI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1137 if (exp->in(1) == iv && exp->in(2)->is_Con()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1138 if (p_scale != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1139 *p_scale = exp->in(2)->get_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
1140 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1141 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1142 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1143 if (exp->in(2) == iv && exp->in(1)->is_Con()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1144 if (p_scale != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1145 *p_scale = exp->in(1)->get_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
1146 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1147 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1148 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1149 } else if (opc == Op_LShiftI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1150 if (exp->in(1) == iv && exp->in(2)->is_Con()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1151 if (p_scale != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1152 *p_scale = 1 << exp->in(2)->get_int();
a61af66fc99e Initial load
duke
parents:
diff changeset
1153 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1154 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1155 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1157 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1158 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1159
a61af66fc99e Initial load
duke
parents:
diff changeset
1160 //-----------------------------is_scaled_iv_plus_offset------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1161 // Return true if exp is a simple induction variable expression: k1*iv + (invar + k2)
a61af66fc99e Initial load
duke
parents:
diff changeset
1162 bool PhaseIdealLoop::is_scaled_iv_plus_offset(Node* exp, Node* iv, int* p_scale, Node** p_offset, int depth) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1163 if (is_scaled_iv(exp, iv, p_scale)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1164 if (p_offset != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1165 Node *zero = _igvn.intcon(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1166 set_ctrl(zero, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1167 *p_offset = zero;
a61af66fc99e Initial load
duke
parents:
diff changeset
1168 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1169 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1170 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1171 int opc = exp->Opcode();
a61af66fc99e Initial load
duke
parents:
diff changeset
1172 if (opc == Op_AddI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1173 if (is_scaled_iv(exp->in(1), iv, p_scale)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1174 if (p_offset != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1175 *p_offset = exp->in(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1176 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1177 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1179 if (exp->in(2)->is_Con()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1180 Node* offset2 = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1181 if (depth < 2 &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1182 is_scaled_iv_plus_offset(exp->in(1), iv, p_scale,
a61af66fc99e Initial load
duke
parents:
diff changeset
1183 p_offset != NULL ? &offset2 : NULL, depth+1)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1184 if (p_offset != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1185 Node *ctrl_off2 = get_ctrl(offset2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1186 Node* offset = new (C, 3) AddINode(offset2, exp->in(2));
a61af66fc99e Initial load
duke
parents:
diff changeset
1187 register_new_node(offset, ctrl_off2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1188 *p_offset = offset;
a61af66fc99e Initial load
duke
parents:
diff changeset
1189 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1190 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1191 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1192 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1193 } else if (opc == Op_SubI) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1194 if (is_scaled_iv(exp->in(1), iv, p_scale)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1195 if (p_offset != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1196 Node *zero = _igvn.intcon(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1197 set_ctrl(zero, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1198 Node *ctrl_off = get_ctrl(exp->in(2));
a61af66fc99e Initial load
duke
parents:
diff changeset
1199 Node* offset = new (C, 3) SubINode(zero, exp->in(2));
a61af66fc99e Initial load
duke
parents:
diff changeset
1200 register_new_node(offset, ctrl_off);
a61af66fc99e Initial load
duke
parents:
diff changeset
1201 *p_offset = offset;
a61af66fc99e Initial load
duke
parents:
diff changeset
1202 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1203 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1204 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1205 if (is_scaled_iv(exp->in(2), iv, p_scale)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1206 if (p_offset != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1207 *p_scale *= -1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1208 *p_offset = exp->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1209 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1210 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1211 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1213 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1215
a61af66fc99e Initial load
duke
parents:
diff changeset
1216 //------------------------------do_range_check---------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1217 // Eliminate range-checks and other trip-counter vs loop-invariant tests.
a61af66fc99e Initial load
duke
parents:
diff changeset
1218 void PhaseIdealLoop::do_range_check( IdealLoopTree *loop, Node_List &old_new ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1219 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1220 if( PrintOpto && VerifyLoopOptimizations ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1221 tty->print("Range Check Elimination ");
a61af66fc99e Initial load
duke
parents:
diff changeset
1222 loop->dump_head();
a61af66fc99e Initial load
duke
parents:
diff changeset
1223 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1224 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1225 assert( RangeCheckElimination, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1226 CountedLoopNode *cl = loop->_head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1227 assert( cl->is_main_loop(), "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1228
a61af66fc99e Initial load
duke
parents:
diff changeset
1229 // Find the trip counter; we are iteration splitting based on it
a61af66fc99e Initial load
duke
parents:
diff changeset
1230 Node *trip_counter = cl->phi();
a61af66fc99e Initial load
duke
parents:
diff changeset
1231 // Find the main loop limit; we will trim it's iterations
a61af66fc99e Initial load
duke
parents:
diff changeset
1232 // to not ever trip end tests
a61af66fc99e Initial load
duke
parents:
diff changeset
1233 Node *main_limit = cl->limit();
a61af66fc99e Initial load
duke
parents:
diff changeset
1234 // Find the pre-loop limit; we will expand it's iterations to
a61af66fc99e Initial load
duke
parents:
diff changeset
1235 // not ever trip low tests.
a61af66fc99e Initial load
duke
parents:
diff changeset
1236 Node *ctrl = cl->in(LoopNode::EntryControl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1237 assert( ctrl->Opcode() == Op_IfTrue || ctrl->Opcode() == Op_IfFalse, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1238 Node *iffm = ctrl->in(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1239 assert( iffm->Opcode() == Op_If, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1240 Node *p_f = iffm->in(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1241 assert( p_f->Opcode() == Op_IfFalse, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1242 CountedLoopEndNode *pre_end = p_f->in(0)->as_CountedLoopEnd();
a61af66fc99e Initial load
duke
parents:
diff changeset
1243 assert( pre_end->loopnode()->is_pre_loop(), "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1244 Node *pre_opaq1 = pre_end->limit();
a61af66fc99e Initial load
duke
parents:
diff changeset
1245 // Occasionally it's possible for a pre-loop Opaque1 node to be
a61af66fc99e Initial load
duke
parents:
diff changeset
1246 // optimized away and then another round of loop opts attempted.
a61af66fc99e Initial load
duke
parents:
diff changeset
1247 // We can not optimize this particular loop in that case.
a61af66fc99e Initial load
duke
parents:
diff changeset
1248 if( pre_opaq1->Opcode() != Op_Opaque1 )
a61af66fc99e Initial load
duke
parents:
diff changeset
1249 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1250 Opaque1Node *pre_opaq = (Opaque1Node*)pre_opaq1;
a61af66fc99e Initial load
duke
parents:
diff changeset
1251 Node *pre_limit = pre_opaq->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1252
a61af66fc99e Initial load
duke
parents:
diff changeset
1253 // Where do we put new limit calculations
a61af66fc99e Initial load
duke
parents:
diff changeset
1254 Node *pre_ctrl = pre_end->loopnode()->in(LoopNode::EntryControl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1255
a61af66fc99e Initial load
duke
parents:
diff changeset
1256 // Ensure the original loop limit is available from the
a61af66fc99e Initial load
duke
parents:
diff changeset
1257 // pre-loop Opaque1 node.
a61af66fc99e Initial load
duke
parents:
diff changeset
1258 Node *orig_limit = pre_opaq->original_loop_limit();
a61af66fc99e Initial load
duke
parents:
diff changeset
1259 if( orig_limit == NULL || _igvn.type(orig_limit) == Type::TOP )
a61af66fc99e Initial load
duke
parents:
diff changeset
1260 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1261
a61af66fc99e Initial load
duke
parents:
diff changeset
1262 // Need to find the main-loop zero-trip guard
a61af66fc99e Initial load
duke
parents:
diff changeset
1263 Node *bolzm = iffm->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1264 assert( bolzm->Opcode() == Op_Bool, "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1265 Node *cmpzm = bolzm->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1266 assert( cmpzm->is_Cmp(), "" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1267 Node *opqzm = cmpzm->in(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1268 if( opqzm->Opcode() != Op_Opaque1 )
a61af66fc99e Initial load
duke
parents:
diff changeset
1269 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1270 assert( opqzm->in(1) == main_limit, "do not understand situation" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1271
a61af66fc99e Initial load
duke
parents:
diff changeset
1272 // Must know if its a count-up or count-down loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1273
a61af66fc99e Initial load
duke
parents:
diff changeset
1274 // protect against stride not being a constant
a61af66fc99e Initial load
duke
parents:
diff changeset
1275 if ( !cl->stride_is_con() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1276 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
1277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1278 int stride_con = cl->stride_con();
a61af66fc99e Initial load
duke
parents:
diff changeset
1279 Node *zero = _igvn.intcon(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
1280 Node *one = _igvn.intcon(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1281 set_ctrl(zero, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1282 set_ctrl(one, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1283
a61af66fc99e Initial load
duke
parents:
diff changeset
1284 // Range checks that do not dominate the loop backedge (ie.
a61af66fc99e Initial load
duke
parents:
diff changeset
1285 // conditionally executed) can lengthen the pre loop limit beyond
a61af66fc99e Initial load
duke
parents:
diff changeset
1286 // the original loop limit. To prevent this, the pre limit is
a61af66fc99e Initial load
duke
parents:
diff changeset
1287 // (for stride > 0) MINed with the original loop limit (MAXed
a61af66fc99e Initial load
duke
parents:
diff changeset
1288 // stride < 0) when some range_check (rc) is conditionally
a61af66fc99e Initial load
duke
parents:
diff changeset
1289 // executed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1290 bool conditional_rc = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1291
a61af66fc99e Initial load
duke
parents:
diff changeset
1292 // Check loop body for tests of trip-counter plus loop-invariant vs
a61af66fc99e Initial load
duke
parents:
diff changeset
1293 // loop-invariant.
a61af66fc99e Initial load
duke
parents:
diff changeset
1294 for( uint i = 0; i < loop->_body.size(); i++ ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1295 Node *iff = loop->_body[i];
a61af66fc99e Initial load
duke
parents:
diff changeset
1296 if( iff->Opcode() == Op_If ) { // Test?
a61af66fc99e Initial load
duke
parents:
diff changeset
1297
a61af66fc99e Initial load
duke
parents:
diff changeset
1298 // Test is an IfNode, has 2 projections. If BOTH are in the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1299 // we need loop unswitching instead of iteration splitting.
a61af66fc99e Initial load
duke
parents:
diff changeset
1300 Node *exit = loop->is_loop_exit(iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
1301 if( !exit ) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
1302 int flip = (exit->Opcode() == Op_IfTrue) ? 1 : 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
1303
a61af66fc99e Initial load
duke
parents:
diff changeset
1304 // Get boolean condition to test
a61af66fc99e Initial load
duke
parents:
diff changeset
1305 Node *i1 = iff->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1306 if( !i1->is_Bool() ) continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
1307 BoolNode *bol = i1->as_Bool();
a61af66fc99e Initial load
duke
parents:
diff changeset
1308 BoolTest b_test = bol->_test;
a61af66fc99e Initial load
duke
parents:
diff changeset
1309 // Flip sense of test if exit condition is flipped
a61af66fc99e Initial load
duke
parents:
diff changeset
1310 if( flip )
a61af66fc99e Initial load
duke
parents:
diff changeset
1311 b_test = b_test.negate();
a61af66fc99e Initial load
duke
parents:
diff changeset
1312
a61af66fc99e Initial load
duke
parents:
diff changeset
1313 // Get compare
a61af66fc99e Initial load
duke
parents:
diff changeset
1314 Node *cmp = bol->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1315
a61af66fc99e Initial load
duke
parents:
diff changeset
1316 // Look for trip_counter + offset vs limit
a61af66fc99e Initial load
duke
parents:
diff changeset
1317 Node *rc_exp = cmp->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1318 Node *limit = cmp->in(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1319 jint scale_con= 1; // Assume trip counter not scaled
a61af66fc99e Initial load
duke
parents:
diff changeset
1320
a61af66fc99e Initial load
duke
parents:
diff changeset
1321 Node *limit_c = get_ctrl(limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1322 if( loop->is_member(get_loop(limit_c) ) ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1323 // Compare might have operands swapped; commute them
a61af66fc99e Initial load
duke
parents:
diff changeset
1324 b_test = b_test.commute();
a61af66fc99e Initial load
duke
parents:
diff changeset
1325 rc_exp = cmp->in(2);
a61af66fc99e Initial load
duke
parents:
diff changeset
1326 limit = cmp->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1327 limit_c = get_ctrl(limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1328 if( loop->is_member(get_loop(limit_c) ) )
a61af66fc99e Initial load
duke
parents:
diff changeset
1329 continue; // Both inputs are loop varying; cannot RCE
a61af66fc99e Initial load
duke
parents:
diff changeset
1330 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1331 // Here we know 'limit' is loop invariant
a61af66fc99e Initial load
duke
parents:
diff changeset
1332
a61af66fc99e Initial load
duke
parents:
diff changeset
1333 // 'limit' maybe pinned below the zero trip test (probably from a
a61af66fc99e Initial load
duke
parents:
diff changeset
1334 // previous round of rce), in which case, it can't be used in the
a61af66fc99e Initial load
duke
parents:
diff changeset
1335 // zero trip test expression which must occur before the zero test's if.
a61af66fc99e Initial load
duke
parents:
diff changeset
1336 if( limit_c == ctrl ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1337 continue; // Don't rce this check but continue looking for other candidates.
a61af66fc99e Initial load
duke
parents:
diff changeset
1338 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1339
a61af66fc99e Initial load
duke
parents:
diff changeset
1340 // Check for scaled induction variable plus an offset
a61af66fc99e Initial load
duke
parents:
diff changeset
1341 Node *offset = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1342
a61af66fc99e Initial load
duke
parents:
diff changeset
1343 if (!is_scaled_iv_plus_offset(rc_exp, trip_counter, &scale_con, &offset)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1344 continue;
a61af66fc99e Initial load
duke
parents:
diff changeset
1345 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1346
a61af66fc99e Initial load
duke
parents:
diff changeset
1347 Node *offset_c = get_ctrl(offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
1348 if( loop->is_member( get_loop(offset_c) ) )
a61af66fc99e Initial load
duke
parents:
diff changeset
1349 continue; // Offset is not really loop invariant
a61af66fc99e Initial load
duke
parents:
diff changeset
1350 // Here we know 'offset' is loop invariant.
a61af66fc99e Initial load
duke
parents:
diff changeset
1351
a61af66fc99e Initial load
duke
parents:
diff changeset
1352 // As above for the 'limit', the 'offset' maybe pinned below the
a61af66fc99e Initial load
duke
parents:
diff changeset
1353 // zero trip test.
a61af66fc99e Initial load
duke
parents:
diff changeset
1354 if( offset_c == ctrl ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1355 continue; // Don't rce this check but continue looking for other candidates.
a61af66fc99e Initial load
duke
parents:
diff changeset
1356 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1357
a61af66fc99e Initial load
duke
parents:
diff changeset
1358 // At this point we have the expression as:
a61af66fc99e Initial load
duke
parents:
diff changeset
1359 // scale_con * trip_counter + offset :: limit
a61af66fc99e Initial load
duke
parents:
diff changeset
1360 // where scale_con, offset and limit are loop invariant. Trip_counter
a61af66fc99e Initial load
duke
parents:
diff changeset
1361 // monotonically increases by stride_con, a constant. Both (or either)
a61af66fc99e Initial load
duke
parents:
diff changeset
1362 // stride_con and scale_con can be negative which will flip about the
a61af66fc99e Initial load
duke
parents:
diff changeset
1363 // sense of the test.
a61af66fc99e Initial load
duke
parents:
diff changeset
1364
a61af66fc99e Initial load
duke
parents:
diff changeset
1365 // Adjust pre and main loop limits to guard the correct iteration set
a61af66fc99e Initial load
duke
parents:
diff changeset
1366 if( cmp->Opcode() == Op_CmpU ) {// Unsigned compare is really 2 tests
a61af66fc99e Initial load
duke
parents:
diff changeset
1367 if( b_test._test == BoolTest::lt ) { // Range checks always use lt
a61af66fc99e Initial load
duke
parents:
diff changeset
1368 // The overflow limit: scale*I+offset < limit
a61af66fc99e Initial load
duke
parents:
diff changeset
1369 add_constraint( stride_con, scale_con, offset, limit, pre_ctrl, &pre_limit, &main_limit );
a61af66fc99e Initial load
duke
parents:
diff changeset
1370 // The underflow limit: 0 <= scale*I+offset.
a61af66fc99e Initial load
duke
parents:
diff changeset
1371 // Some math yields: -scale*I-(offset+1) < 0
a61af66fc99e Initial load
duke
parents:
diff changeset
1372 Node *plus_one = new (C, 3) AddINode( offset, one );
a61af66fc99e Initial load
duke
parents:
diff changeset
1373 register_new_node( plus_one, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1374 Node *neg_offset = new (C, 3) SubINode( zero, plus_one );
a61af66fc99e Initial load
duke
parents:
diff changeset
1375 register_new_node( neg_offset, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1376 add_constraint( stride_con, -scale_con, neg_offset, zero, pre_ctrl, &pre_limit, &main_limit );
a61af66fc99e Initial load
duke
parents:
diff changeset
1377 if (!conditional_rc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1378 conditional_rc = !loop->dominates_backedge(iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
1379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1380 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1381 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1382 if( PrintOpto )
a61af66fc99e Initial load
duke
parents:
diff changeset
1383 tty->print_cr("missed RCE opportunity");
a61af66fc99e Initial load
duke
parents:
diff changeset
1384 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1385 continue; // In release mode, ignore it
a61af66fc99e Initial load
duke
parents:
diff changeset
1386 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1387 } else { // Otherwise work on normal compares
a61af66fc99e Initial load
duke
parents:
diff changeset
1388 switch( b_test._test ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1389 case BoolTest::ge: // Convert X >= Y to -X <= -Y
a61af66fc99e Initial load
duke
parents:
diff changeset
1390 scale_con = -scale_con;
a61af66fc99e Initial load
duke
parents:
diff changeset
1391 offset = new (C, 3) SubINode( zero, offset );
a61af66fc99e Initial load
duke
parents:
diff changeset
1392 register_new_node( offset, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1393 limit = new (C, 3) SubINode( zero, limit );
a61af66fc99e Initial load
duke
parents:
diff changeset
1394 register_new_node( limit, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1395 // Fall into LE case
a61af66fc99e Initial load
duke
parents:
diff changeset
1396 case BoolTest::le: // Convert X <= Y to X < Y+1
a61af66fc99e Initial load
duke
parents:
diff changeset
1397 limit = new (C, 3) AddINode( limit, one );
a61af66fc99e Initial load
duke
parents:
diff changeset
1398 register_new_node( limit, pre_ctrl );
a61af66fc99e Initial load
duke
parents:
diff changeset
1399 // Fall into LT case
a61af66fc99e Initial load
duke
parents:
diff changeset
1400 case BoolTest::lt:
a61af66fc99e Initial load
duke
parents:
diff changeset
1401 add_constraint( stride_con, scale_con, offset, limit, pre_ctrl, &pre_limit, &main_limit );
a61af66fc99e Initial load
duke
parents:
diff changeset
1402 if (!conditional_rc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1403 conditional_rc = !loop->dominates_backedge(iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
1404 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1405 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
1406 default:
a61af66fc99e Initial load
duke
parents:
diff changeset
1407 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1408 if( PrintOpto )
a61af66fc99e Initial load
duke
parents:
diff changeset
1409 tty->print_cr("missed RCE opportunity");
a61af66fc99e Initial load
duke
parents:
diff changeset
1410 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1411 continue; // Unhandled case
a61af66fc99e Initial load
duke
parents:
diff changeset
1412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1413 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1414
a61af66fc99e Initial load
duke
parents:
diff changeset
1415 // Kill the eliminated test
a61af66fc99e Initial load
duke
parents:
diff changeset
1416 C->set_major_progress();
a61af66fc99e Initial load
duke
parents:
diff changeset
1417 Node *kill_con = _igvn.intcon( 1-flip );
a61af66fc99e Initial load
duke
parents:
diff changeset
1418 set_ctrl(kill_con, C->root());
a61af66fc99e Initial load
duke
parents:
diff changeset
1419 _igvn.hash_delete(iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
1420 iff->set_req(1, kill_con);
a61af66fc99e Initial load
duke
parents:
diff changeset
1421 _igvn._worklist.push(iff);
a61af66fc99e Initial load
duke
parents:
diff changeset
1422 // Find surviving projection
a61af66fc99e Initial load
duke
parents:
diff changeset
1423 assert(iff->is_If(), "");
a61af66fc99e Initial load
duke
parents:
diff changeset
1424 ProjNode* dp = ((IfNode*)iff)->proj_out(1-flip);
a61af66fc99e Initial load
duke
parents:
diff changeset
1425 // Find loads off the surviving projection; remove their control edge
a61af66fc99e Initial load
duke
parents:
diff changeset
1426 for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1427 Node* cd = dp->fast_out(i); // Control-dependent node
a61af66fc99e Initial load
duke
parents:
diff changeset
1428 if( cd->is_Load() ) { // Loads can now float around in the loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1429 _igvn.hash_delete(cd);
a61af66fc99e Initial load
duke
parents:
diff changeset
1430 // Allow the load to float around in the loop, or before it
a61af66fc99e Initial load
duke
parents:
diff changeset
1431 // but NOT before the pre-loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
1432 cd->set_req(0, ctrl); // ctrl, not NULL
a61af66fc99e Initial load
duke
parents:
diff changeset
1433 _igvn._worklist.push(cd);
a61af66fc99e Initial load
duke
parents:
diff changeset
1434 --i;
a61af66fc99e Initial load
duke
parents:
diff changeset
1435 --imax;
a61af66fc99e Initial load
duke
parents:
diff changeset
1436 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1437 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1438
a61af66fc99e Initial load
duke
parents:
diff changeset
1439 } // End of is IF
a61af66fc99e Initial load
duke
parents:
diff changeset
1440
a61af66fc99e Initial load
duke
parents:
diff changeset
1441 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1442
a61af66fc99e Initial load
duke
parents:
diff changeset
1443 // Update loop limits
a61af66fc99e Initial load
duke
parents:
diff changeset
1444 if (conditional_rc) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1445 pre_limit = (stride_con > 0) ? (Node*)new (C,3) MinINode(pre_limit, orig_limit)
a61af66fc99e Initial load
duke
parents:
diff changeset
1446 : (Node*)new (C,3) MaxINode(pre_limit, orig_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1447 register_new_node(pre_limit, pre_ctrl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1448 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1449 _igvn.hash_delete(pre_opaq);
a61af66fc99e Initial load
duke
parents:
diff changeset
1450 pre_opaq->set_req(1, pre_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1451
a61af66fc99e Initial load
duke
parents:
diff changeset
1452 // Note:: we are making the main loop limit no longer precise;
a61af66fc99e Initial load
duke
parents:
diff changeset
1453 // need to round up based on stride.
a61af66fc99e Initial load
duke
parents:
diff changeset
1454 if( stride_con != 1 && stride_con != -1 ) { // Cutout for common case
a61af66fc99e Initial load
duke
parents:
diff changeset
1455 // "Standard" round-up logic: ([main_limit-init+(y-1)]/y)*y+init
a61af66fc99e Initial load
duke
parents:
diff changeset
1456 // Hopefully, compiler will optimize for powers of 2.
a61af66fc99e Initial load
duke
parents:
diff changeset
1457 Node *ctrl = get_ctrl(main_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1458 Node *stride = cl->stride();
a61af66fc99e Initial load
duke
parents:
diff changeset
1459 Node *init = cl->init_trip();
a61af66fc99e Initial load
duke
parents:
diff changeset
1460 Node *span = new (C, 3) SubINode(main_limit,init);
a61af66fc99e Initial load
duke
parents:
diff changeset
1461 register_new_node(span,ctrl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1462 Node *rndup = _igvn.intcon(stride_con + ((stride_con>0)?-1:1));
a61af66fc99e Initial load
duke
parents:
diff changeset
1463 Node *add = new (C, 3) AddINode(span,rndup);
a61af66fc99e Initial load
duke
parents:
diff changeset
1464 register_new_node(add,ctrl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1465 Node *div = new (C, 3) DivINode(0,add,stride);
a61af66fc99e Initial load
duke
parents:
diff changeset
1466 register_new_node(div,ctrl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1467 Node *mul = new (C, 3) MulINode(div,stride);
a61af66fc99e Initial load
duke
parents:
diff changeset
1468 register_new_node(mul,ctrl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1469 Node *newlim = new (C, 3) AddINode(mul,init);
a61af66fc99e Initial load
duke
parents:
diff changeset
1470 register_new_node(newlim,ctrl);
a61af66fc99e Initial load
duke
parents:
diff changeset
1471 main_limit = newlim;
a61af66fc99e Initial load
duke
parents:
diff changeset
1472 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1473
a61af66fc99e Initial load
duke
parents:
diff changeset
1474 Node *main_cle = cl->loopexit();
a61af66fc99e Initial load
duke
parents:
diff changeset
1475 Node *main_bol = main_cle->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1476 // Hacking loop bounds; need private copies of exit test
a61af66fc99e Initial load
duke
parents:
diff changeset
1477 if( main_bol->outcnt() > 1 ) {// BoolNode shared?
a61af66fc99e Initial load
duke
parents:
diff changeset
1478 _igvn.hash_delete(main_cle);
a61af66fc99e Initial load
duke
parents:
diff changeset
1479 main_bol = main_bol->clone();// Clone a private BoolNode
a61af66fc99e Initial load
duke
parents:
diff changeset
1480 register_new_node( main_bol, main_cle->in(0) );
a61af66fc99e Initial load
duke
parents:
diff changeset
1481 main_cle->set_req(1,main_bol);
a61af66fc99e Initial load
duke
parents:
diff changeset
1482 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1483 Node *main_cmp = main_bol->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1484 if( main_cmp->outcnt() > 1 ) { // CmpNode shared?
a61af66fc99e Initial load
duke
parents:
diff changeset
1485 _igvn.hash_delete(main_bol);
a61af66fc99e Initial load
duke
parents:
diff changeset
1486 main_cmp = main_cmp->clone();// Clone a private CmpNode
a61af66fc99e Initial load
duke
parents:
diff changeset
1487 register_new_node( main_cmp, main_cle->in(0) );
a61af66fc99e Initial load
duke
parents:
diff changeset
1488 main_bol->set_req(1,main_cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1489 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1490 // Hack the now-private loop bounds
a61af66fc99e Initial load
duke
parents:
diff changeset
1491 _igvn.hash_delete(main_cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1492 main_cmp->set_req(2, main_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1493 _igvn._worklist.push(main_cmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
1494 // The OpaqueNode is unshared by design
a61af66fc99e Initial load
duke
parents:
diff changeset
1495 _igvn.hash_delete(opqzm);
a61af66fc99e Initial load
duke
parents:
diff changeset
1496 assert( opqzm->outcnt() == 1, "cannot hack shared node" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1497 opqzm->set_req(1,main_limit);
a61af66fc99e Initial load
duke
parents:
diff changeset
1498 _igvn._worklist.push(opqzm);
a61af66fc99e Initial load
duke
parents:
diff changeset
1499 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1500
a61af66fc99e Initial load
duke
parents:
diff changeset
1501 //------------------------------DCE_loop_body----------------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1502 // Remove simplistic dead code from loop body
a61af66fc99e Initial load
duke
parents:
diff changeset
1503 void IdealLoopTree::DCE_loop_body() {
a61af66fc99e Initial load
duke
parents:
diff changeset
1504 for( uint i = 0; i < _body.size(); i++ )
a61af66fc99e Initial load
duke
parents:
diff changeset
1505 if( _body.at(i)->outcnt() == 0 )
a61af66fc99e Initial load
duke
parents:
diff changeset
1506 _body.map( i--, _body.pop() );
a61af66fc99e Initial load
duke
parents:
diff changeset
1507 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1508
a61af66fc99e Initial load
duke
parents:
diff changeset
1509
a61af66fc99e Initial load
duke
parents:
diff changeset
1510 //------------------------------adjust_loop_exit_prob--------------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1511 // Look for loop-exit tests with the 50/50 (or worse) guesses from the parsing stage.
a61af66fc99e Initial load
duke
parents:
diff changeset
1512 // Replace with a 1-in-10 exit guess.
a61af66fc99e Initial load
duke
parents:
diff changeset
1513 void IdealLoopTree::adjust_loop_exit_prob( PhaseIdealLoop *phase ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1514 Node *test = tail();
a61af66fc99e Initial load
duke
parents:
diff changeset
1515 while( test != _head ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1516 uint top = test->Opcode();
a61af66fc99e Initial load
duke
parents:
diff changeset
1517 if( top == Op_IfTrue || top == Op_IfFalse ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1518 int test_con = ((ProjNode*)test)->_con;
a61af66fc99e Initial load
duke
parents:
diff changeset
1519 assert(top == (uint)(test_con? Op_IfTrue: Op_IfFalse), "sanity");
a61af66fc99e Initial load
duke
parents:
diff changeset
1520 IfNode *iff = test->in(0)->as_If();
a61af66fc99e Initial load
duke
parents:
diff changeset
1521 if( iff->outcnt() == 2 ) { // Ignore dead tests
a61af66fc99e Initial load
duke
parents:
diff changeset
1522 Node *bol = iff->in(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
1523 if( bol && bol->req() > 1 && bol->in(1) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1524 ((bol->in(1)->Opcode() == Op_StorePConditional ) ||
420
a1980da045cc 6462850: generate biased locking code in C2 ideal graph
kvn
parents: 401
diff changeset
1525 (bol->in(1)->Opcode() == Op_StoreIConditional ) ||
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1526 (bol->in(1)->Opcode() == Op_StoreLConditional ) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1527 (bol->in(1)->Opcode() == Op_CompareAndSwapI ) ||
a61af66fc99e Initial load
duke
parents:
diff changeset
1528 (bol->in(1)->Opcode() == Op_CompareAndSwapL ) ||
113
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 39
diff changeset
1529 (bol->in(1)->Opcode() == Op_CompareAndSwapP ) ||
ba764ed4b6f2 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 39
diff changeset
1530 (bol->in(1)->Opcode() == Op_CompareAndSwapN )))
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1531 return; // Allocation loops RARELY take backedge
a61af66fc99e Initial load
duke
parents:
diff changeset
1532 // Find the OTHER exit path from the IF
a61af66fc99e Initial load
duke
parents:
diff changeset
1533 Node* ex = iff->proj_out(1-test_con);
a61af66fc99e Initial load
duke
parents:
diff changeset
1534 float p = iff->_prob;
a61af66fc99e Initial load
duke
parents:
diff changeset
1535 if( !phase->is_member( this, ex ) && iff->_fcnt == COUNT_UNKNOWN ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1536 if( top == Op_IfTrue ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1537 if( p < (PROB_FAIR + PROB_UNLIKELY_MAG(3))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1538 iff->_prob = PROB_STATIC_FREQUENT;
a61af66fc99e Initial load
duke
parents:
diff changeset
1539 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1540 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
1541 if( p > (PROB_FAIR - PROB_UNLIKELY_MAG(3))) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1542 iff->_prob = PROB_STATIC_INFREQUENT;
a61af66fc99e Initial load
duke
parents:
diff changeset
1543 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1544 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1545 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1546 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1547 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1548 test = phase->idom(test);
a61af66fc99e Initial load
duke
parents:
diff changeset
1549 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1550 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1551
a61af66fc99e Initial load
duke
parents:
diff changeset
1552
a61af66fc99e Initial load
duke
parents:
diff changeset
1553 //------------------------------policy_do_remove_empty_loop--------------------
a61af66fc99e Initial load
duke
parents:
diff changeset
1554 // Micro-benchmark spamming. Policy is to always remove empty loops.
a61af66fc99e Initial load
duke
parents:
diff changeset
1555 // The 'DO' part is to replace the trip counter with the value it will
a61af66fc99e Initial load
duke
parents:
diff changeset
1556 // have on the last iteration. This will break the loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
1557 bool IdealLoopTree::policy_do_remove_empty_loop( PhaseIdealLoop *phase ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1558 // Minimum size must be empty loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1559 if( _body.size() > 7/*number of nodes in an empty loop*/ ) return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
1560
a61af66fc99e Initial load
duke
parents:
diff changeset
1561 if( !_head->is_CountedLoop() ) return false; // Dead loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1562 CountedLoopNode *cl = _head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1563 if( !cl->loopexit() ) return false; // Malformed loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1564 if( !phase->is_member(this,phase->get_ctrl(cl->loopexit()->in(CountedLoopEndNode::TestValue)) ) )
a61af66fc99e Initial load
duke
parents:
diff changeset
1565 return false; // Infinite loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1566 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1567 if( PrintOpto )
a61af66fc99e Initial load
duke
parents:
diff changeset
1568 tty->print_cr("Removing empty loop");
a61af66fc99e Initial load
duke
parents:
diff changeset
1569 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1570 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
1571 // Ensure only one phi which is the iv.
a61af66fc99e Initial load
duke
parents:
diff changeset
1572 Node* iv = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
1573 for (DUIterator_Fast imax, i = cl->fast_outs(imax); i < imax; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1574 Node* n = cl->fast_out(i);
a61af66fc99e Initial load
duke
parents:
diff changeset
1575 if (n->Opcode() == Op_Phi) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1576 assert(iv == NULL, "Too many phis" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1577 iv = n;
a61af66fc99e Initial load
duke
parents:
diff changeset
1578 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1579 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1580 assert(iv == cl->phi(), "Wrong phi" );
a61af66fc99e Initial load
duke
parents:
diff changeset
1581 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1582 // Replace the phi at loop head with the final value of the last
a61af66fc99e Initial load
duke
parents:
diff changeset
1583 // iteration. Then the CountedLoopEnd will collapse (backedge never
a61af66fc99e Initial load
duke
parents:
diff changeset
1584 // taken) and all loop-invariant uses of the exit values will be correct.
a61af66fc99e Initial load
duke
parents:
diff changeset
1585 Node *phi = cl->phi();
a61af66fc99e Initial load
duke
parents:
diff changeset
1586 Node *final = new (phase->C, 3) SubINode( cl->limit(), cl->stride() );
a61af66fc99e Initial load
duke
parents:
diff changeset
1587 phase->register_new_node(final,cl->in(LoopNode::EntryControl));
1621
6027dddc26c6 6677629: PhaseIterGVN::subsume_node() should call hash_delete() and add_users_to_worklist()
kvn
parents: 1552
diff changeset
1588 phase->_igvn.replace_node(phi,final);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1589 phase->C->set_major_progress();
a61af66fc99e Initial load
duke
parents:
diff changeset
1590 return true;
a61af66fc99e Initial load
duke
parents:
diff changeset
1591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1592
a61af66fc99e Initial load
duke
parents:
diff changeset
1593
a61af66fc99e Initial load
duke
parents:
diff changeset
1594 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
1595 //------------------------------iteration_split_impl---------------------------
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1596 bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_new ) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1597 // Check and remove empty loops (spam micro-benchmarks)
a61af66fc99e Initial load
duke
parents:
diff changeset
1598 if( policy_do_remove_empty_loop(phase) )
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1599 return true; // Here we removed an empty loop
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1600
a61af66fc99e Initial load
duke
parents:
diff changeset
1601 bool should_peel = policy_peeling(phase); // Should we peel?
a61af66fc99e Initial load
duke
parents:
diff changeset
1602
a61af66fc99e Initial load
duke
parents:
diff changeset
1603 bool should_unswitch = policy_unswitching(phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
1604
a61af66fc99e Initial load
duke
parents:
diff changeset
1605 // Non-counted loops may be peeled; exactly 1 iteration is peeled.
a61af66fc99e Initial load
duke
parents:
diff changeset
1606 // This removes loop-invariant tests (usually null checks).
a61af66fc99e Initial load
duke
parents:
diff changeset
1607 if( !_head->is_CountedLoop() ) { // Non-counted loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1608 if (PartialPeelLoop && phase->partial_peel(this, old_new)) {
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1609 // Partial peel succeeded so terminate this round of loop opts
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1610 return false;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1611 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1612 if( should_peel ) { // Should we peel?
a61af66fc99e Initial load
duke
parents:
diff changeset
1613 #ifndef PRODUCT
a61af66fc99e Initial load
duke
parents:
diff changeset
1614 if (PrintOpto) tty->print_cr("should_peel");
a61af66fc99e Initial load
duke
parents:
diff changeset
1615 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
1616 phase->do_peeling(this,old_new);
a61af66fc99e Initial load
duke
parents:
diff changeset
1617 } else if( should_unswitch ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1618 phase->do_unswitching(this, old_new);
a61af66fc99e Initial load
duke
parents:
diff changeset
1619 }
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1620 return true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1621 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1622 CountedLoopNode *cl = _head->as_CountedLoop();
a61af66fc99e Initial load
duke
parents:
diff changeset
1623
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1624 if( !cl->loopexit() ) return true; // Ignore various kinds of broken loops
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1625
a61af66fc99e Initial load
duke
parents:
diff changeset
1626 // Do nothing special to pre- and post- loops
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1627 if( cl->is_pre_loop() || cl->is_post_loop() ) return true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1628
a61af66fc99e Initial load
duke
parents:
diff changeset
1629 // Compute loop trip count from profile data
a61af66fc99e Initial load
duke
parents:
diff changeset
1630 compute_profile_trip_cnt(phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
1631
a61af66fc99e Initial load
duke
parents:
diff changeset
1632 // Before attempting fancy unrolling, RCE or alignment, see if we want
a61af66fc99e Initial load
duke
parents:
diff changeset
1633 // to completely unroll this loop or do loop unswitching.
a61af66fc99e Initial load
duke
parents:
diff changeset
1634 if( cl->is_normal_loop() ) {
789
273b2358ef1a 6837146: Should perform unswitch before maximally unroll in loop transformation
cfang
parents: 605
diff changeset
1635 if (should_unswitch) {
273b2358ef1a 6837146: Should perform unswitch before maximally unroll in loop transformation
cfang
parents: 605
diff changeset
1636 phase->do_unswitching(this, old_new);
273b2358ef1a 6837146: Should perform unswitch before maximally unroll in loop transformation
cfang
parents: 605
diff changeset
1637 return true;
273b2358ef1a 6837146: Should perform unswitch before maximally unroll in loop transformation
cfang
parents: 605
diff changeset
1638 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1639 bool should_maximally_unroll = policy_maximally_unroll(phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
1640 if( should_maximally_unroll ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1641 // Here we did some unrolling and peeling. Eventually we will
a61af66fc99e Initial load
duke
parents:
diff changeset
1642 // completely unroll this loop and it will no longer be a loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
1643 phase->do_maximally_unroll(this,old_new);
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1644 return true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1645 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1646 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1647
a61af66fc99e Initial load
duke
parents:
diff changeset
1648
a61af66fc99e Initial load
duke
parents:
diff changeset
1649 // Counted loops may be peeled, may need some iterations run up
a61af66fc99e Initial load
duke
parents:
diff changeset
1650 // front for RCE, and may want to align loop refs to a cache
a61af66fc99e Initial load
duke
parents:
diff changeset
1651 // line. Thus we clone a full loop up front whose trip count is
a61af66fc99e Initial load
duke
parents:
diff changeset
1652 // at least 1 (if peeling), but may be several more.
a61af66fc99e Initial load
duke
parents:
diff changeset
1653
a61af66fc99e Initial load
duke
parents:
diff changeset
1654 // The main loop will start cache-line aligned with at least 1
a61af66fc99e Initial load
duke
parents:
diff changeset
1655 // iteration of the unrolled body (zero-trip test required) and
a61af66fc99e Initial load
duke
parents:
diff changeset
1656 // will have some range checks removed.
a61af66fc99e Initial load
duke
parents:
diff changeset
1657
a61af66fc99e Initial load
duke
parents:
diff changeset
1658 // A post-loop will finish any odd iterations (leftover after
a61af66fc99e Initial load
duke
parents:
diff changeset
1659 // unrolling), plus any needed for RCE purposes.
a61af66fc99e Initial load
duke
parents:
diff changeset
1660
a61af66fc99e Initial load
duke
parents:
diff changeset
1661 bool should_unroll = policy_unroll(phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
1662
a61af66fc99e Initial load
duke
parents:
diff changeset
1663 bool should_rce = policy_range_check(phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
1664
a61af66fc99e Initial load
duke
parents:
diff changeset
1665 bool should_align = policy_align(phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
1666
a61af66fc99e Initial load
duke
parents:
diff changeset
1667 // If not RCE'ing (iteration splitting) or Aligning, then we do not
a61af66fc99e Initial load
duke
parents:
diff changeset
1668 // need a pre-loop. We may still need to peel an initial iteration but
a61af66fc99e Initial load
duke
parents:
diff changeset
1669 // we will not be needing an unknown number of pre-iterations.
a61af66fc99e Initial load
duke
parents:
diff changeset
1670 //
a61af66fc99e Initial load
duke
parents:
diff changeset
1671 // Basically, if may_rce_align reports FALSE first time through,
a61af66fc99e Initial load
duke
parents:
diff changeset
1672 // we will not be able to later do RCE or Aligning on this loop.
a61af66fc99e Initial load
duke
parents:
diff changeset
1673 bool may_rce_align = !policy_peel_only(phase) || should_rce || should_align;
a61af66fc99e Initial load
duke
parents:
diff changeset
1674
a61af66fc99e Initial load
duke
parents:
diff changeset
1675 // If we have any of these conditions (RCE, alignment, unrolling) met, then
a61af66fc99e Initial load
duke
parents:
diff changeset
1676 // we switch to the pre-/main-/post-loop model. This model also covers
a61af66fc99e Initial load
duke
parents:
diff changeset
1677 // peeling.
a61af66fc99e Initial load
duke
parents:
diff changeset
1678 if( should_rce || should_align || should_unroll ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1679 if( cl->is_normal_loop() ) // Convert to 'pre/main/post' loops
a61af66fc99e Initial load
duke
parents:
diff changeset
1680 phase->insert_pre_post_loops(this,old_new, !may_rce_align);
a61af66fc99e Initial load
duke
parents:
diff changeset
1681
a61af66fc99e Initial load
duke
parents:
diff changeset
1682 // Adjust the pre- and main-loop limits to let the pre and post loops run
a61af66fc99e Initial load
duke
parents:
diff changeset
1683 // with full checks, but the main-loop with no checks. Remove said
a61af66fc99e Initial load
duke
parents:
diff changeset
1684 // checks from the main body.
a61af66fc99e Initial load
duke
parents:
diff changeset
1685 if( should_rce )
a61af66fc99e Initial load
duke
parents:
diff changeset
1686 phase->do_range_check(this,old_new);
a61af66fc99e Initial load
duke
parents:
diff changeset
1687
a61af66fc99e Initial load
duke
parents:
diff changeset
1688 // Double loop body for unrolling. Adjust the minimum-trip test (will do
a61af66fc99e Initial load
duke
parents:
diff changeset
1689 // twice as many iterations as before) and the main body limit (only do
a61af66fc99e Initial load
duke
parents:
diff changeset
1690 // an even number of trips). If we are peeling, we might enable some RCE
a61af66fc99e Initial load
duke
parents:
diff changeset
1691 // and we'd rather unroll the post-RCE'd loop SO... do not unroll if
a61af66fc99e Initial load
duke
parents:
diff changeset
1692 // peeling.
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1693 if( should_unroll && !should_peel )
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1694 phase->do_unroll(this,old_new, true);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1695
a61af66fc99e Initial load
duke
parents:
diff changeset
1696 // Adjust the pre-loop limits to align the main body
a61af66fc99e Initial load
duke
parents:
diff changeset
1697 // iterations.
a61af66fc99e Initial load
duke
parents:
diff changeset
1698 if( should_align )
a61af66fc99e Initial load
duke
parents:
diff changeset
1699 Unimplemented();
a61af66fc99e Initial load
duke
parents:
diff changeset
1700
a61af66fc99e Initial load
duke
parents:
diff changeset
1701 } else { // Else we have an unchanged counted loop
a61af66fc99e Initial load
duke
parents:
diff changeset
1702 if( should_peel ) // Might want to peel but do nothing else
a61af66fc99e Initial load
duke
parents:
diff changeset
1703 phase->do_peeling(this,old_new);
a61af66fc99e Initial load
duke
parents:
diff changeset
1704 }
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1705 return true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1706 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1707
a61af66fc99e Initial load
duke
parents:
diff changeset
1708
a61af66fc99e Initial load
duke
parents:
diff changeset
1709 //=============================================================================
a61af66fc99e Initial load
duke
parents:
diff changeset
1710 //------------------------------iteration_split--------------------------------
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1711 bool IdealLoopTree::iteration_split( PhaseIdealLoop *phase, Node_List &old_new ) {
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1712 // Recursively iteration split nested loops
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1713 if( _child && !_child->iteration_split( phase, old_new ))
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1714 return false;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1715
a61af66fc99e Initial load
duke
parents:
diff changeset
1716 // Clean out prior deadwood
a61af66fc99e Initial load
duke
parents:
diff changeset
1717 DCE_loop_body();
a61af66fc99e Initial load
duke
parents:
diff changeset
1718
a61af66fc99e Initial load
duke
parents:
diff changeset
1719
a61af66fc99e Initial load
duke
parents:
diff changeset
1720 // Look for loop-exit tests with my 50/50 guesses from the Parsing stage.
a61af66fc99e Initial load
duke
parents:
diff changeset
1721 // Replace with a 1-in-10 exit guess.
a61af66fc99e Initial load
duke
parents:
diff changeset
1722 if( _parent /*not the root loop*/ &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1723 !_irreducible &&
a61af66fc99e Initial load
duke
parents:
diff changeset
1724 // Also ignore the occasional dead backedge
a61af66fc99e Initial load
duke
parents:
diff changeset
1725 !tail()->is_top() ) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1726 adjust_loop_exit_prob(phase);
a61af66fc99e Initial load
duke
parents:
diff changeset
1727 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1728
a61af66fc99e Initial load
duke
parents:
diff changeset
1729
a61af66fc99e Initial load
duke
parents:
diff changeset
1730 // Gate unrolling, RCE and peeling efforts.
a61af66fc99e Initial load
duke
parents:
diff changeset
1731 if( !_child && // If not an inner loop, do not split
a61af66fc99e Initial load
duke
parents:
diff changeset
1732 !_irreducible &&
39
76256d272075 6667612: (Escape Analysis) disable loop cloning if it has a scalar replaceable allocation
kvn
parents: 0
diff changeset
1733 _allow_optimizations &&
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1734 !tail()->is_top() ) { // Also ignore the occasional dead backedge
a61af66fc99e Initial load
duke
parents:
diff changeset
1735 if (!_has_call) {
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1736 if (!iteration_split_impl( phase, old_new )) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1737 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1738 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1739 } else if (policy_unswitching(phase)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
1740 phase->do_unswitching(this, old_new);
a61af66fc99e Initial load
duke
parents:
diff changeset
1741 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1742 }
a61af66fc99e Initial load
duke
parents:
diff changeset
1743
a61af66fc99e Initial load
duke
parents:
diff changeset
1744 // Minor offset re-organization to remove loop-fallout uses of
a61af66fc99e Initial load
duke
parents:
diff changeset
1745 // trip counter.
a61af66fc99e Initial load
duke
parents:
diff changeset
1746 if( _head->is_CountedLoop() ) phase->reorg_offsets( this );
401
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1747 if( _next && !_next->iteration_split( phase, old_new ))
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1748 return false;
ee8f06bfb27c 6743188: incomplete fix for 6700047 C2 failed in idom_no_update
never
parents: 400
diff changeset
1749 return true;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1750 }
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1751
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1752 //-------------------------------is_uncommon_trap_proj----------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1753 // Return true if proj is the form of "proj->[region->..]call_uct"
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1754 bool PhaseIdealLoop::is_uncommon_trap_proj(ProjNode* proj, bool must_reason_predicate) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1755 int path_limit = 10;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1756 assert(proj, "invalid argument");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1757 Node* out = proj;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1758 for (int ct = 0; ct < path_limit; ct++) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1759 out = out->unique_ctrl_out();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1760 if (out == NULL || out->is_Root() || out->is_Start())
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1761 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1762 if (out->is_CallStaticJava()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1763 int req = out->as_CallStaticJava()->uncommon_trap_request();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1764 if (req != 0) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1765 Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(req);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1766 if (!must_reason_predicate || reason == Deoptimization::Reason_predicate){
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1767 return true;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1768 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1769 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1770 return false; // don't do further after call
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1771 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1772 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1773 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1774 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1775
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1776 //-------------------------------is_uncommon_trap_if_pattern-------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1777 // Return true for "if(test)-> proj -> ...
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1778 // |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1779 // V
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1780 // other_proj->[region->..]call_uct"
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1781 //
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1782 // "must_reason_predicate" means the uct reason must be Reason_predicate
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1783 bool PhaseIdealLoop::is_uncommon_trap_if_pattern(ProjNode *proj, bool must_reason_predicate) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1784 Node *in0 = proj->in(0);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1785 if (!in0->is_If()) return false;
1280
336c6c200f5f 6930116: loop predication code does not handle If nodes with only one projection
kvn
parents: 1275
diff changeset
1786 // Variation of a dead If node.
336c6c200f5f 6930116: loop predication code does not handle If nodes with only one projection
kvn
parents: 1275
diff changeset
1787 if (in0->outcnt() < 2) return false;
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1788 IfNode* iff = in0->as_If();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1789
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1790 // we need "If(Conv2B(Opaque1(...)))" pattern for must_reason_predicate
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1791 if (must_reason_predicate) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1792 if (iff->in(1)->Opcode() != Op_Conv2B ||
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1793 iff->in(1)->in(1)->Opcode() != Op_Opaque1) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1794 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1795 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1796 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1797
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1798 ProjNode* other_proj = iff->proj_out(1-proj->_con)->as_Proj();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1799 return is_uncommon_trap_proj(other_proj, must_reason_predicate);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1800 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1801
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1802 //------------------------------create_new_if_for_predicate------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1803 // create a new if above the uct_if_pattern for the predicate to be promoted.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1804 //
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1805 // before after
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1806 // ---------- ----------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1807 // ctrl ctrl
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1808 // | |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1809 // | |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1810 // v v
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1811 // iff new_iff
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1812 // / \ / \
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1813 // / \ / \
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1814 // v v v v
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1815 // uncommon_proj cont_proj if_uct if_cont
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1816 // \ | | | |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1817 // \ | | | |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1818 // v v v | v
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1819 // rgn loop | iff
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1820 // | | / \
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1821 // | | / \
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1822 // v | v v
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1823 // uncommon_trap | uncommon_proj cont_proj
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1824 // \ \ | |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1825 // \ \ | |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1826 // v v v v
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1827 // rgn loop
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1828 // |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1829 // |
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1830 // v
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1831 // uncommon_trap
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1832 //
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1833 //
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1834 // We will create a region to guard the uct call if there is no one there.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1835 // The true projecttion (if_cont) of the new_iff is returned.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1836 ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1837 assert(is_uncommon_trap_if_pattern(cont_proj, true), "must be a uct if pattern!");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1838 IfNode* iff = cont_proj->in(0)->as_If();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1839
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1840 ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1841 Node *rgn = uncommon_proj->unique_ctrl_out();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1842 assert(rgn->is_Region() || rgn->is_Call(), "must be a region or call uct");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1843
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1844 if (!rgn->is_Region()) { // create a region to guard the call
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1845 assert(rgn->is_Call(), "must be call uct");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1846 CallNode* call = rgn->as_Call();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1847 rgn = new (C, 1) RegionNode(1);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1848 _igvn.set_type(rgn, rgn->bottom_type());
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1849 rgn->add_req(uncommon_proj);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1850 set_idom(rgn, idom(uncommon_proj), dom_depth(uncommon_proj)+1);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1851 _igvn.hash_delete(call);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1852 call->set_req(0, rgn);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1853 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1854
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1855 // Create new_iff
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1856 uint iffdd = dom_depth(iff);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1857 IdealLoopTree* lp = get_loop(iff);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1858 IfNode *new_iff = new (C, 2) IfNode(iff->in(0), NULL, iff->_prob, iff->_fcnt);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1859 register_node(new_iff, lp, idom(iff), iffdd);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1860 Node *if_cont = new (C, 1) IfTrueNode(new_iff);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1861 Node *if_uct = new (C, 1) IfFalseNode(new_iff);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1862 if (cont_proj->is_IfFalse()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1863 // Swap
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1864 Node* tmp = if_uct; if_uct = if_cont; if_cont = tmp;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1865 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1866 register_node(if_cont, lp, new_iff, iffdd);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1867 register_node(if_uct, get_loop(rgn), new_iff, iffdd);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1868
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1869 // if_cont to iff
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1870 _igvn.hash_delete(iff);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1871 iff->set_req(0, if_cont);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1872 set_idom(iff, if_cont, dom_depth(iff));
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1873
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1874 // if_uct to rgn
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1875 _igvn.hash_delete(rgn);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1876 rgn->add_req(if_uct);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1877 Node* ridom = idom(rgn);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1878 Node* nrdom = dom_lca(ridom, new_iff);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1879 set_idom(rgn, nrdom, dom_depth(rgn));
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1880
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1881 // rgn must have no phis
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1882 assert(!rgn->as_Region()->has_phi(), "region must have no phis");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1883
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1884 return if_cont->as_Proj();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1885 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1886
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1887 //------------------------------find_predicate_insertion_point--------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1888 // Find a good location to insert a predicate
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1889 ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1890 if (start_c == C->root() || !start_c->is_Proj())
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1891 return NULL;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1892 if (is_uncommon_trap_if_pattern(start_c->as_Proj(), true/*Reason_Predicate*/)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1893 return start_c->as_Proj();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1894 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1895 return NULL;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1896 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1897
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1898 //------------------------------Invariance-----------------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1899 // Helper class for loop_predication_impl to compute invariance on the fly and
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1900 // clone invariants.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1901 class Invariance : public StackObj {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1902 VectorSet _visited, _invariant;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1903 Node_Stack _stack;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1904 VectorSet _clone_visited;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1905 Node_List _old_new; // map of old to new (clone)
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1906 IdealLoopTree* _lpt;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1907 PhaseIdealLoop* _phase;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1908
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1909 // Helper function to set up the invariance for invariance computation
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1910 // If n is a known invariant, set up directly. Otherwise, look up the
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1911 // the possibility to push n onto the stack for further processing.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1912 void visit(Node* use, Node* n) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1913 if (_lpt->is_invariant(n)) { // known invariant
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1914 _invariant.set(n->_idx);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1915 } else if (!n->is_CFG()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1916 Node *n_ctrl = _phase->ctrl_or_self(n);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1917 Node *u_ctrl = _phase->ctrl_or_self(use); // self if use is a CFG
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1918 if (_phase->is_dominator(n_ctrl, u_ctrl)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1919 _stack.push(n, n->in(0) == NULL ? 1 : 0);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1920 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1921 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1922 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1923
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1924 // Compute invariance for "the_node" and (possibly) all its inputs recursively
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1925 // on the fly
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1926 void compute_invariance(Node* n) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1927 assert(_visited.test(n->_idx), "must be");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1928 visit(n, n);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1929 while (_stack.is_nonempty()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1930 Node* n = _stack.node();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1931 uint idx = _stack.index();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1932 if (idx == n->req()) { // all inputs are processed
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1933 _stack.pop();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1934 // n is invariant if it's inputs are all invariant
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1935 bool all_inputs_invariant = true;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1936 for (uint i = 0; i < n->req(); i++) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1937 Node* in = n->in(i);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1938 if (in == NULL) continue;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1939 assert(_visited.test(in->_idx), "must have visited input");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1940 if (!_invariant.test(in->_idx)) { // bad guy
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1941 all_inputs_invariant = false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1942 break;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1943 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1944 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1945 if (all_inputs_invariant) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1946 _invariant.set(n->_idx); // I am a invariant too
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1947 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1948 } else { // process next input
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1949 _stack.set_index(idx + 1);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1950 Node* m = n->in(idx);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1951 if (m != NULL && !_visited.test_set(m->_idx)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1952 visit(n, m);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1953 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1954 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1955 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1956 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1957
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1958 // Helper function to set up _old_new map for clone_nodes.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1959 // If n is a known invariant, set up directly ("clone" of n == n).
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1960 // Otherwise, push n onto the stack for real cloning.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1961 void clone_visit(Node* n) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1962 assert(_invariant.test(n->_idx), "must be invariant");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1963 if (_lpt->is_invariant(n)) { // known invariant
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1964 _old_new.map(n->_idx, n);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1965 } else{ // to be cloned
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1966 assert (!n->is_CFG(), "should not see CFG here");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1967 _stack.push(n, n->in(0) == NULL ? 1 : 0);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1968 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1969 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1970
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1971 // Clone "n" and (possibly) all its inputs recursively
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1972 void clone_nodes(Node* n, Node* ctrl) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1973 clone_visit(n);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1974 while (_stack.is_nonempty()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1975 Node* n = _stack.node();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1976 uint idx = _stack.index();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1977 if (idx == n->req()) { // all inputs processed, clone n!
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1978 _stack.pop();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1979 // clone invariant node
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1980 Node* n_cl = n->clone();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1981 _old_new.map(n->_idx, n_cl);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1982 _phase->register_new_node(n_cl, ctrl);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1983 for (uint i = 0; i < n->req(); i++) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1984 Node* in = n_cl->in(i);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1985 if (in == NULL) continue;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1986 n_cl->set_req(i, _old_new[in->_idx]);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1987 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1988 } else { // process next input
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1989 _stack.set_index(idx + 1);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1990 Node* m = n->in(idx);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1991 if (m != NULL && !_clone_visited.test_set(m->_idx)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1992 clone_visit(m); // visit the input
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1993 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1994 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1995 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1996 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1997
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1998 public:
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
1999 Invariance(Arena* area, IdealLoopTree* lpt) :
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2000 _lpt(lpt), _phase(lpt->_phase),
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2001 _visited(area), _invariant(area), _stack(area, 10 /* guess */),
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2002 _clone_visited(area), _old_new(area)
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2003 {}
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2004
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2005 // Map old to n for invariance computation and clone
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2006 void map_ctrl(Node* old, Node* n) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2007 assert(old->is_CFG() && n->is_CFG(), "must be");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2008 _old_new.map(old->_idx, n); // "clone" of old is n
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2009 _invariant.set(old->_idx); // old is invariant
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2010 _clone_visited.set(old->_idx);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2011 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2012
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2013 // Driver function to compute invariance
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2014 bool is_invariant(Node* n) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2015 if (!_visited.test_set(n->_idx))
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2016 compute_invariance(n);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2017 return (_invariant.test(n->_idx) != 0);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2018 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2019
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2020 // Driver function to clone invariant
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2021 Node* clone(Node* n, Node* ctrl) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2022 assert(ctrl->is_CFG(), "must be");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2023 assert(_invariant.test(n->_idx), "must be an invariant");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2024 if (!_clone_visited.test(n->_idx))
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2025 clone_nodes(n, ctrl);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2026 return _old_new[n->_idx];
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2027 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2028 };
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2029
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2030 //------------------------------is_range_check_if -----------------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2031 // Returns true if the predicate of iff is in "scale*iv + offset u< load_range(ptr)" format
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2032 // Note: this function is particularly designed for loop predication. We require load_range
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2033 // and offset to be loop invariant computed on the fly by "invar"
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2034 bool IdealLoopTree::is_range_check_if(IfNode *iff, PhaseIdealLoop *phase, Invariance& invar) const {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2035 if (!is_loop_exit(iff)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2036 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2037 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2038 if (!iff->in(1)->is_Bool()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2039 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2040 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2041 const BoolNode *bol = iff->in(1)->as_Bool();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2042 if (bol->_test._test != BoolTest::lt) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2043 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2044 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2045 if (!bol->in(1)->is_Cmp()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2046 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2047 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2048 const CmpNode *cmp = bol->in(1)->as_Cmp();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2049 if (cmp->Opcode() != Op_CmpU ) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2050 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2051 }
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2052 Node* range = cmp->in(2);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2053 if (range->Opcode() != Op_LoadRange) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2054 const TypeInt* tint = phase->_igvn.type(range)->isa_int();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2055 if (!OptimizeFill || tint == NULL || tint->empty() || tint->_lo < 0) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2056 // Allow predication on positive values that aren't LoadRanges.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2057 // This allows optimization of loops where the length of the
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2058 // array is a known value and doesn't need to be loaded back
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2059 // from the array.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2060 return false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2061 }
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2062 }
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2063 if (!invar.is_invariant(range)) {
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2064 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2065 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2066 Node *iv = _head->as_CountedLoop()->phi();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2067 int scale = 0;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2068 Node *offset = NULL;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2069 if (!phase->is_scaled_iv_plus_offset(cmp->in(1), iv, &scale, &offset)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2070 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2071 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2072 if(offset && !invar.is_invariant(offset)) { // offset must be invariant
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2073 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2074 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2075 return true;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2076 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2077
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2078 //------------------------------rc_predicate-----------------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2079 // Create a range check predicate
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2080 //
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2081 // for (i = init; i < limit; i += stride) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2082 // a[scale*i+offset]
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2083 // }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2084 //
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2085 // Compute max(scale*i + offset) for init <= i < limit and build the predicate
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2086 // as "max(scale*i + offset) u< a.length".
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2087 //
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2088 // There are two cases for max(scale*i + offset):
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2089 // (1) stride*scale > 0
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2090 // max(scale*i + offset) = scale*(limit-stride) + offset
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2091 // (2) stride*scale < 0
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2092 // max(scale*i + offset) = scale*init + offset
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2093 BoolNode* PhaseIdealLoop::rc_predicate(Node* ctrl,
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2094 int scale, Node* offset,
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2095 Node* init, Node* limit, Node* stride,
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2096 Node* range, bool upper) {
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2097 DEBUG_ONLY(ttyLocker ttyl);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2098 if (TraceLoopPredicate) tty->print("rc_predicate ");
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2099
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2100 Node* max_idx_expr = init;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2101 int stride_con = stride->get_int();
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2102 if ((stride_con > 0) == (scale > 0) == upper) {
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2103 max_idx_expr = new (C, 3) SubINode(limit, stride);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2104 register_new_node(max_idx_expr, ctrl);
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2105 if (TraceLoopPredicate) tty->print("(limit - stride) ");
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2106 } else {
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2107 if (TraceLoopPredicate) tty->print("init ");
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2108 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2109
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2110 if (scale != 1) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2111 ConNode* con_scale = _igvn.intcon(scale);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2112 max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2113 register_new_node(max_idx_expr, ctrl);
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2114 if (TraceLoopPredicate) tty->print("* %d ", scale);
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2115 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2116
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2117 if (offset && (!offset->is_Con() || offset->get_int() != 0)){
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2118 max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2119 register_new_node(max_idx_expr, ctrl);
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2120 if (TraceLoopPredicate)
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2121 if (offset->is_Con()) tty->print("+ %d ", offset->get_int());
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2122 else tty->print("+ offset ");
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2123 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2124
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2125 CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2126 register_new_node(cmp, ctrl);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2127 BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2128 register_new_node(bol, ctrl);
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2129
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2130 if (TraceLoopPredicate) tty->print_cr("<u range");
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2131 return bol;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2132 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2133
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2134 //------------------------------ loop_predication_impl--------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2135 // Insert loop predicates for null checks and range checks
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2136 bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2137 if (!UseLoopPredicate) return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2138
1275
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2139 if (!loop->_head->is_Loop()) {
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2140 // Could be a simple region when irreducible loops are present.
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2141 return false;
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2142 }
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2143
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2144 CountedLoopNode *cl = NULL;
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2145 if (loop->_head->is_CountedLoop()) {
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2146 cl = loop->_head->as_CountedLoop();
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2147 // do nothing for iteration-splitted loops
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2148 if (!cl->is_normal_loop()) return false;
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2149 }
b71f13525cc8 6927049: assert(is_Loop(),"invalid node class")
never
parents: 1172
diff changeset
2150
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2151 // Too many traps seen?
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2152 bool tmt = C->too_many_traps(C->method(), 0, Deoptimization::Reason_predicate);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2153 int tc = C->trap_count(Deoptimization::Reason_predicate);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2154 if (tmt || tc > 0) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2155 if (TraceLoopPredicate) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2156 tty->print_cr("too many predicate traps: %d", tc);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2157 C->method()->print(); // which method has too many predicate traps
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2158 tty->print_cr("");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2159 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2160 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2161 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2162
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2163 LoopNode *lpn = loop->_head->as_Loop();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2164 Node* entry = lpn->in(LoopNode::EntryControl);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2165
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2166 ProjNode *predicate_proj = find_predicate_insertion_point(entry);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2167 if (!predicate_proj){
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2168 #ifndef PRODUCT
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2169 if (TraceLoopPredicate) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2170 tty->print("missing predicate:");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2171 loop->dump_head();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2172 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2173 #endif
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2174 return false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2175 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2176
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2177 ConNode* zero = _igvn.intcon(0);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2178 set_ctrl(zero, C->root());
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2179 Node *cond_false = new (C, 2) Conv2BNode(zero);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2180 register_new_node(cond_false, C->root());
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2181 ConNode* one = _igvn.intcon(1);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2182 set_ctrl(one, C->root());
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2183 Node *cond_true = new (C, 2) Conv2BNode(one);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2184 register_new_node(cond_true, C->root());
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2185
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2186 ResourceArea *area = Thread::current()->resource_area();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2187 Invariance invar(area, loop);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2188
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2189 // Create list of if-projs such that a newer proj dominates all older
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2190 // projs in the list, and they all dominate loop->tail()
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2191 Node_List if_proj_list(area);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2192 LoopNode *head = loop->_head->as_Loop();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2193 Node *current_proj = loop->tail(); //start from tail
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2194 while ( current_proj != head ) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2195 if (loop == get_loop(current_proj) && // still in the loop ?
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2196 current_proj->is_Proj() && // is a projection ?
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2197 current_proj->in(0)->Opcode() == Op_If) { // is a if projection ?
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2198 if_proj_list.push(current_proj);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2199 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2200 current_proj = idom(current_proj);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2201 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2202
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2203 bool hoisted = false; // true if at least one proj is promoted
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2204 while (if_proj_list.size() > 0) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2205 // Following are changed to nonnull when a predicate can be hoisted
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2206 ProjNode* new_predicate_proj = NULL;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2207
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2208 ProjNode* proj = if_proj_list.pop()->as_Proj();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2209 IfNode* iff = proj->in(0)->as_If();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2210
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2211 if (!is_uncommon_trap_if_pattern(proj)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2212 if (loop->is_loop_exit(iff)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2213 // stop processing the remaining projs in the list because the execution of them
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2214 // depends on the condition of "iff" (iff->in(1)).
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2215 break;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2216 } else {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2217 // Both arms are inside the loop. There are two cases:
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2218 // (1) there is one backward branch. In this case, any remaining proj
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2219 // in the if_proj list post-dominates "iff". So, the condition of "iff"
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2220 // does not determine the execution the remining projs directly, and we
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2221 // can safely continue.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2222 // (2) both arms are forwarded, i.e. a diamond shape. In this case, "proj"
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2223 // does not dominate loop->tail(), so it can not be in the if_proj list.
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2224 continue;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2225 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2226 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2227
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2228 Node* test = iff->in(1);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2229 if (!test->is_Bool()){ //Conv2B, ...
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2230 continue;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2231 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2232 BoolNode* bol = test->as_Bool();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2233 if (invar.is_invariant(bol)) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2234 // Invariant test
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2235 new_predicate_proj = create_new_if_for_predicate(predicate_proj);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2236 Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0);
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2237 BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2238
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2239 // Negate test if necessary
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2240 bool negated = false;
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2241 if (proj->_con != predicate_proj->_con) {
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2242 new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate());
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2243 register_new_node(new_predicate_bol, ctrl);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2244 negated = true;
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2245 }
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2246 IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2247 _igvn.hash_delete(new_predicate_iff);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2248 new_predicate_iff->set_req(1, new_predicate_bol);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2249 if (TraceLoopPredicate) tty->print_cr("invariant if%s: %d", negated ? " negated" : "", new_predicate_iff->_idx);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2250
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2251 } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) {
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2252 assert(proj->_con == predicate_proj->_con, "must match");
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2253
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2254 // Range check for counted loops
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2255 const Node* cmp = bol->in(1)->as_Cmp();
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2256 Node* idx = cmp->in(1);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2257 assert(!invar.is_invariant(idx), "index is variant");
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2258 assert(cmp->in(2)->Opcode() == Op_LoadRange || OptimizeFill, "must be");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2259 Node* rng = cmp->in(2);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2260 assert(invar.is_invariant(rng), "range must be invariant");
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2261 int scale = 1;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2262 Node* offset = zero;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2263 bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2264 assert(ok, "must be index expression");
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2265
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2266 Node* init = cl->init_trip();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2267 Node* limit = cl->limit();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2268 Node* stride = cl->stride();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2269
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2270 // Build if's for the upper and lower bound tests. The
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2271 // lower_bound test will dominate the upper bound test and all
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2272 // cloned or created nodes will use the lower bound test as
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2273 // their declared control.
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2274 ProjNode* lower_bound_proj = create_new_if_for_predicate(predicate_proj);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2275 ProjNode* upper_bound_proj = create_new_if_for_predicate(predicate_proj);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2276 assert(upper_bound_proj->in(0)->as_If()->in(0) == lower_bound_proj, "should dominate");
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2277 Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2278
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2279 // Perform cloning to keep Invariance state correct since the
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2280 // late schedule will place invariant things in the loop.
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2281 rng = invar.clone(rng, ctrl);
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2282 if (offset && offset != zero) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2283 assert(invar.is_invariant(offset), "offset must be loop invariant");
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2284 offset = invar.clone(offset, ctrl);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2285 }
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2286
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2287 // Test the lower bound
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2288 Node* lower_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, rng, false);
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2289 IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2290 _igvn.hash_delete(lower_bound_iff);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2291 lower_bound_iff->set_req(1, lower_bound_bol);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2292 if (TraceLoopPredicate) tty->print_cr("lower bound check if: %d", lower_bound_iff->_idx);
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2293
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2294 // Test the upper bound
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2295 Node* upper_bound_bol = rc_predicate(ctrl, scale, offset, init, limit, stride, rng, true);
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2296 IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2297 _igvn.hash_delete(upper_bound_iff);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2298 upper_bound_iff->set_req(1, upper_bound_bol);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2299 if (TraceLoopPredicate) tty->print_cr("upper bound check if: %d", lower_bound_iff->_idx);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2300
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2301 // Fall through into rest of the clean up code which will move
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2302 // any dependent nodes onto the upper bound test.
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2303 new_predicate_proj = upper_bound_proj;
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2304 } else {
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2305 // The other proj of the "iff" is a uncommon trap projection, and we can assume
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2306 // the other proj will not be executed ("executed" means uct raised).
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2307 continue;
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2308 }
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2309
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2310 // Success - attach condition (new_predicate_bol) to predicate if
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2311 invar.map_ctrl(proj, new_predicate_proj); // so that invariance test can be appropriate
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2312
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2313 // Eliminate the old if in the loop body
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2314 _igvn.hash_delete(iff);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2315 iff->set_req(1, proj->is_IfFalse() ? cond_false : cond_true);
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2316
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2317 Node* ctrl = new_predicate_proj; // new control
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2318 ProjNode* dp = proj; // old control
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2319 assert(get_loop(dp) == loop, "guaranteed at the time of collecting proj");
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2320 // Find nodes (depends only on the test) off the surviving projection;
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2321 // move them outside the loop with the control of proj_clone
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2322 for (DUIterator_Fast imax, i = dp->fast_outs(imax); i < imax; i++) {
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2323 Node* cd = dp->fast_out(i); // Control-dependent node
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2324 if (cd->depends_only_on_test()) {
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2325 assert(cd->in(0) == dp, "");
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2326 _igvn.hash_delete(cd);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2327 cd->set_req(0, ctrl); // ctrl, not NULL
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2328 set_early_ctrl(cd);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2329 _igvn._worklist.push(cd);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2330 IdealLoopTree *new_loop = get_loop(get_ctrl(cd));
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2331 if (new_loop != loop) {
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2332 if (!loop->_child) loop->_body.yank(cd);
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2333 if (!new_loop->_child ) new_loop->_body.push(cd);
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2334 }
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2335 --i;
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2336 --imax;
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2337 }
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2338 }
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2339
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2340 hoisted = true;
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2341 C->set_major_progress();
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2342 } // end while
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2343
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2344 #ifndef PRODUCT
1303
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2345 // report that the loop predication has been actually performed
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2346 // for this loop
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2347 if (TraceLoopPredicate && hoisted) {
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2348 tty->print("Loop Predication Performed:");
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2349 loop->dump_head();
c047da02984c 6930043: C2: SIGSEGV in javasoft.sqe.tests.lang.arr017.arr01702.arr01702.loop_forw(II)I
never
parents: 1280
diff changeset
2350 }
1172
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2351 #endif
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2352
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2353 return hoisted;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2354 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2355
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2356 //------------------------------loop_predication--------------------------------
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2357 // driver routine for loop predication optimization
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2358 bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2359 bool hoisted = false;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2360 // Recursively promote predicates
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2361 if ( _child ) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2362 hoisted = _child->loop_predication( phase);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2363 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2364
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2365 // self
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2366 if (!_irreducible && !tail()->is_top()) {
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2367 hoisted |= phase->loop_predication_impl(this);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2368 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2369
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2370 if ( _next ) { //sibling
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2371 hoisted |= _next->loop_predication( phase);
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2372 }
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2373
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2374 return hoisted;
b2b6a9bf6238 6894779: Loop Predication for Loop Optimizer in C2
cfang
parents: 844
diff changeset
2375 }
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2376
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2377
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2378 // Process all the loops in the loop tree and replace any fill
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2379 // patterns with an intrisc version.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2380 bool PhaseIdealLoop::do_intrinsify_fill() {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2381 bool changed = false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2382 for (LoopTreeIterator iter(_ltree_root); !iter.done(); iter.next()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2383 IdealLoopTree* lpt = iter.current();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2384 changed |= intrinsify_fill(lpt);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2385 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2386 return changed;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2387 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2388
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2389
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2390 // Examine an inner loop looking for a a single store of an invariant
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2391 // value in a unit stride loop,
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2392 bool PhaseIdealLoop::match_fill_loop(IdealLoopTree* lpt, Node*& store, Node*& store_value,
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2393 Node*& shift, Node*& con) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2394 const char* msg = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2395 Node* msg_node = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2396
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2397 store_value = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2398 con = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2399 shift = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2400
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2401 // Process the loop looking for stores. If there are multiple
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2402 // stores or extra control flow give at this point.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2403 CountedLoopNode* head = lpt->_head->as_CountedLoop();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2404 for (uint i = 0; msg == NULL && i < lpt->_body.size(); i++) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2405 Node* n = lpt->_body.at(i);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2406 if (n->outcnt() == 0) continue; // Ignore dead
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2407 if (n->is_Store()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2408 if (store != NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2409 msg = "multiple stores";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2410 break;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2411 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2412 int opc = n->Opcode();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2413 if (opc == Op_StoreP || opc == Op_StoreN || opc == Op_StoreCM) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2414 msg = "oop fills not handled";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2415 break;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2416 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2417 Node* value = n->in(MemNode::ValueIn);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2418 if (!lpt->is_invariant(value)) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2419 msg = "variant store value";
1785
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2420 } else if (!_igvn.type(n->in(MemNode::Address))->isa_aryptr()) {
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2421 msg = "not array address";
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2422 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2423 store = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2424 store_value = value;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2425 } else if (n->is_If() && n != head->loopexit()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2426 msg = "extra control flow";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2427 msg_node = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2428 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2429 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2430
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2431 if (store == NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2432 // No store in loop
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2433 return false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2434 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2435
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2436 if (msg == NULL && head->stride_con() != 1) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2437 // could handle negative strides too
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2438 if (head->stride_con() < 0) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2439 msg = "negative stride";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2440 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2441 msg = "non-unit stride";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2442 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2443 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2444
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2445 if (msg == NULL && !store->in(MemNode::Address)->is_AddP()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2446 msg = "can't handle store address";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2447 msg_node = store->in(MemNode::Address);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2448 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2449
1813
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2450 if (msg == NULL &&
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2451 (!store->in(MemNode::Memory)->is_Phi() ||
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2452 store->in(MemNode::Memory)->in(LoopNode::LoopBackControl) != store)) {
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2453 msg = "store memory isn't proper phi";
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2454 msg_node = store->in(MemNode::Memory);
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2455 }
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2456
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2457 // Make sure there is an appropriate fill routine
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2458 BasicType t = store->as_Mem()->memory_type();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2459 const char* fill_name;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2460 if (msg == NULL &&
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2461 StubRoutines::select_fill_function(t, false, fill_name) == NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2462 msg = "unsupported store";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2463 msg_node = store;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2464 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2465
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2466 if (msg != NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2467 #ifndef PRODUCT
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2468 if (TraceOptimizeFill) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2469 tty->print_cr("not fill intrinsic candidate: %s", msg);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2470 if (msg_node != NULL) msg_node->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2471 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2472 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2473 return false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2474 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2475
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2476 // Make sure the address expression can be handled. It should be
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2477 // head->phi * elsize + con. head->phi might have a ConvI2L.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2478 Node* elements[4];
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2479 Node* conv = NULL;
1785
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2480 bool found_index = false;
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2481 int count = store->in(MemNode::Address)->as_AddP()->unpack_offsets(elements, ARRAY_SIZE(elements));
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2482 for (int e = 0; e < count; e++) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2483 Node* n = elements[e];
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2484 if (n->is_Con() && con == NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2485 con = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2486 } else if (n->Opcode() == Op_LShiftX && shift == NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2487 Node* value = n->in(1);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2488 #ifdef _LP64
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2489 if (value->Opcode() == Op_ConvI2L) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2490 conv = value;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2491 value = value->in(1);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2492 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2493 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2494 if (value != head->phi()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2495 msg = "unhandled shift in address";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2496 } else {
1785
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2497 found_index = true;
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2498 shift = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2499 assert(type2aelembytes(store->as_Mem()->memory_type(), true) == 1 << shift->in(2)->get_int(), "scale should match");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2500 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2501 } else if (n->Opcode() == Op_ConvI2L && conv == NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2502 if (n->in(1) == head->phi()) {
1785
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2503 found_index = true;
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2504 conv = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2505 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2506 msg = "unhandled input to ConvI2L";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2507 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2508 } else if (n == head->phi()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2509 // no shift, check below for allowed cases
1785
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2510 found_index = true;
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2511 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2512 msg = "unhandled node in address";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2513 msg_node = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2514 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2515 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2516
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2517 if (count == -1) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2518 msg = "malformed address expression";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2519 msg_node = store;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2520 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2521
1785
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2522 if (!found_index) {
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2523 msg = "missing use of index";
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2524 }
5e4f03302987 6982533: Crash in ~StubRoutines::jbyte_fill with AggressiveOpts enabled
never
parents: 1763
diff changeset
2525
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2526 // byte sized items won't have a shift
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2527 if (msg == NULL && shift == NULL && t != T_BYTE && t != T_BOOLEAN) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2528 msg = "can't find shift";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2529 msg_node = store;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2530 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2531
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2532 if (msg != NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2533 #ifndef PRODUCT
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2534 if (TraceOptimizeFill) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2535 tty->print_cr("not fill intrinsic: %s", msg);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2536 if (msg_node != NULL) msg_node->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2537 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2538 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2539 return false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2540 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2541
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2542 // No make sure all the other nodes in the loop can be handled
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2543 VectorSet ok(Thread::current()->resource_area());
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2544
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2545 // store related values are ok
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2546 ok.set(store->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2547 ok.set(store->in(MemNode::Memory)->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2548
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2549 // Loop structure is ok
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2550 ok.set(head->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2551 ok.set(head->loopexit()->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2552 ok.set(head->phi()->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2553 ok.set(head->incr()->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2554 ok.set(head->loopexit()->cmp_node()->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2555 ok.set(head->loopexit()->in(1)->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2556
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2557 // Address elements are ok
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2558 if (con) ok.set(con->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2559 if (shift) ok.set(shift->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2560 if (conv) ok.set(conv->_idx);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2561
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2562 for (uint i = 0; msg == NULL && i < lpt->_body.size(); i++) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2563 Node* n = lpt->_body.at(i);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2564 if (n->outcnt() == 0) continue; // Ignore dead
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2565 if (ok.test(n->_idx)) continue;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2566 // Backedge projection is ok
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2567 if (n->is_IfTrue() && n->in(0) == head->loopexit()) continue;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2568 if (!n->is_AddP()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2569 msg = "unhandled node";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2570 msg_node = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2571 break;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2572 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2573 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2574
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2575 // Make sure no unexpected values are used outside the loop
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2576 for (uint i = 0; msg == NULL && i < lpt->_body.size(); i++) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2577 Node* n = lpt->_body.at(i);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2578 // These values can be replaced with other nodes if they are used
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2579 // outside the loop.
1813
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2580 if (n == store || n == head->loopexit() || n == head->incr() || n == store->in(MemNode::Memory)) continue;
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2581 for (SimpleDUIterator iter(n); iter.has_next(); iter.next()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2582 Node* use = iter.get();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2583 if (!lpt->_body.contains(use)) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2584 msg = "node is used outside loop";
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2585 // lpt->_body.dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2586 msg_node = n;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2587 break;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2588 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2589 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2590 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2591
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2592 #ifdef ASSERT
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2593 if (TraceOptimizeFill) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2594 if (msg != NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2595 tty->print_cr("no fill intrinsic: %s", msg);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2596 if (msg_node != NULL) msg_node->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2597 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2598 tty->print_cr("fill intrinsic for:");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2599 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2600 store->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2601 if (Verbose) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2602 lpt->_body.dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2603 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2604 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2605 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2606
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2607 return msg == NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2608 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2609
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2610
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2611
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2612 bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2613 // Only for counted inner loops
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2614 if (!lpt->is_counted() || !lpt->is_inner()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2615 return false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2616 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2617
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2618 // Must have constant stride
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2619 CountedLoopNode* head = lpt->_head->as_CountedLoop();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2620 if (!head->stride_is_con() || !head->is_normal_loop()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2621 return false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2622 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2623
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2624 // Check that the body only contains a store of a loop invariant
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2625 // value that is indexed by the loop phi.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2626 Node* store = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2627 Node* store_value = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2628 Node* shift = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2629 Node* offset = NULL;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2630 if (!match_fill_loop(lpt, store, store_value, shift, offset)) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2631 return false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2632 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2633
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2634 // Now replace the whole loop body by a call to a fill routine that
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2635 // covers the same region as the loop.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2636 Node* base = store->in(MemNode::Address)->as_AddP()->in(AddPNode::Base);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2637
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2638 // Build an expression for the beginning of the copy region
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2639 Node* index = head->init_trip();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2640 #ifdef _LP64
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2641 index = new (C, 2) ConvI2LNode(index);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2642 _igvn.register_new_node_with_optimizer(index);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2643 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2644 if (shift != NULL) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2645 // byte arrays don't require a shift but others do.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2646 index = new (C, 3) LShiftXNode(index, shift->in(2));
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2647 _igvn.register_new_node_with_optimizer(index);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2648 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2649 index = new (C, 4) AddPNode(base, base, index);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2650 _igvn.register_new_node_with_optimizer(index);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2651 Node* from = new (C, 4) AddPNode(base, index, offset);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2652 _igvn.register_new_node_with_optimizer(from);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2653 // Compute the number of elements to copy
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2654 Node* len = new (C, 3) SubINode(head->limit(), head->init_trip());
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2655 _igvn.register_new_node_with_optimizer(len);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2656
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2657 BasicType t = store->as_Mem()->memory_type();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2658 bool aligned = false;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2659 if (offset != NULL && head->init_trip()->is_Con()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2660 int element_size = type2aelembytes(t);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2661 aligned = (offset->find_intptr_t_type()->get_con() + head->init_trip()->get_int() * element_size) % HeapWordSize == 0;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2662 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2663
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2664 // Build a call to the fill routine
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2665 const char* fill_name;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2666 address fill = StubRoutines::select_fill_function(t, aligned, fill_name);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2667 assert(fill != NULL, "what?");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2668
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2669 // Convert float/double to int/long for fill routines
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2670 if (t == T_FLOAT) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2671 store_value = new (C, 2) MoveF2INode(store_value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2672 _igvn.register_new_node_with_optimizer(store_value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2673 } else if (t == T_DOUBLE) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2674 store_value = new (C, 2) MoveD2LNode(store_value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2675 _igvn.register_new_node_with_optimizer(store_value);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2676 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2677
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2678 Node* mem_phi = store->in(MemNode::Memory);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2679 Node* result_ctrl;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2680 Node* result_mem;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2681 const TypeFunc* call_type = OptoRuntime::array_fill_Type();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2682 int size = call_type->domain()->cnt();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2683 CallLeafNode *call = new (C, size) CallLeafNoFPNode(call_type, fill,
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2684 fill_name, TypeAryPtr::get_array_body_type(t));
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2685 call->init_req(TypeFunc::Parms+0, from);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2686 call->init_req(TypeFunc::Parms+1, store_value);
1844
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1813
diff changeset
2687 #ifdef _LP64
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1813
diff changeset
2688 len = new (C, 2) ConvI2LNode(len);
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1813
diff changeset
2689 _igvn.register_new_node_with_optimizer(len);
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1813
diff changeset
2690 #endif
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2691 call->init_req(TypeFunc::Parms+2, len);
1844
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1813
diff changeset
2692 #ifdef _LP64
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1813
diff changeset
2693 call->init_req(TypeFunc::Parms+3, C->top());
75588558f1bf 6980792: Crash "exception happened outside interpreter, nmethods and vtable stubs (1)"
never
parents: 1813
diff changeset
2694 #endif
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2695 call->init_req( TypeFunc::Control, head->init_control());
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2696 call->init_req( TypeFunc::I_O , C->top() ) ; // does no i/o
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2697 call->init_req( TypeFunc::Memory , mem_phi->in(LoopNode::EntryControl) );
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2698 call->init_req( TypeFunc::ReturnAdr, C->start()->proj_out(TypeFunc::ReturnAdr) );
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2699 call->init_req( TypeFunc::FramePtr, C->start()->proj_out(TypeFunc::FramePtr) );
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2700 _igvn.register_new_node_with_optimizer(call);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2701 result_ctrl = new (C, 1) ProjNode(call,TypeFunc::Control);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2702 _igvn.register_new_node_with_optimizer(result_ctrl);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2703 result_mem = new (C, 1) ProjNode(call,TypeFunc::Memory);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2704 _igvn.register_new_node_with_optimizer(result_mem);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2705
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2706 // If this fill is tightly coupled to an allocation and overwrites
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2707 // the whole body, allow it to take over the zeroing.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2708 AllocateNode* alloc = AllocateNode::Ideal_allocation(base, this);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2709 if (alloc != NULL && alloc->is_AllocateArray()) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2710 Node* length = alloc->as_AllocateArray()->Ideal_length();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2711 if (head->limit() == length &&
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2712 head->init_trip() == _igvn.intcon(0)) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2713 if (TraceOptimizeFill) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2714 tty->print_cr("Eliminated zeroing in allocation");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2715 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2716 alloc->maybe_set_complete(&_igvn);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2717 } else {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2718 #ifdef ASSERT
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2719 if (TraceOptimizeFill) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2720 tty->print_cr("filling array but bounds don't match");
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2721 alloc->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2722 head->init_trip()->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2723 head->limit()->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2724 length->dump();
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2725 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2726 #endif
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2727 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2728 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2729
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2730 // Redirect the old control and memory edges that are outside the loop.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2731 Node* exit = head->loopexit()->proj_out(0);
1813
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2732 // Sometimes the memory phi of the head is used as the outgoing
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2733 // state of the loop. It's safe in this case to replace it with the
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2734 // result_mem.
c77e8f982901 6984979: OptimizeFill misses some cases with an odd memory graph
never
parents: 1785
diff changeset
2735 _igvn.replace_node(store->in(MemNode::Memory), result_mem);
1763
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2736 _igvn.replace_node(exit, result_ctrl);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2737 _igvn.replace_node(store, result_mem);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2738 // Any uses the increment outside of the loop become the loop limit.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2739 _igvn.replace_node(head->incr(), head->limit());
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2740
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2741 // Disconnect the head from the loop.
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2742 for (uint i = 0; i < lpt->_body.size(); i++) {
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2743 Node* n = lpt->_body.at(i);
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2744 _igvn.replace_node(n, C->top());
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2745 }
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2746
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2747 return true;
d6f45b55c972 4809552: Optimize Arrays.fill(...)
never
parents: 1621
diff changeset
2748 }