annotate src/share/vm/opto/loopPredicate.cpp @ 6972:bd7a7ce2e264

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