annotate src/share/vm/opto/loopPredicate.cpp @ 4710:41406797186b

7113012: G1: rename not-fully-young GCs as "mixed" Summary: Renamed partially-young GCs as mixed and fully-young GCs as young. Change all external output that includes those terms (GC log and GC ergo log) as well as any comments, fields, methods, etc. The changeset also includes very minor code tidying up (added some curly brackets). Reviewed-by: johnc, brutisso
author tonyp
date Fri, 16 Dec 2011 02:14:27 -0500
parents 6987871cfb9b
children 5e990493719e
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 /*
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
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);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
162 rgn = new (C, 1) RegionNode(1);
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);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
188 Node *if_cont = new (C, 1) IfTrueNode(new_iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
189 Node *if_uct = new (C, 1) IfFalseNode(new_iff);
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, "");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
215 _igvn.hash_delete(use);
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 _igvn._worklist.push(use);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
218 has_phi = true;
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 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
221 assert(!has_phi || rgn->req() > 3, "no phis when region is created");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
222
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
223 if (new_entry == NULL) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
224 // Attach if_cont to iff
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
225 _igvn.hash_delete(iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
226 iff->set_req(0, if_cont);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
227 if (_idom != NULL) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
228 set_idom(iff, if_cont, dom_depth(iff));
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 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
231 return if_cont->as_Proj();
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
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
234 //------------------------------create_new_if_for_predicate------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
235 // 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
236 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
237 Deoptimization::DeoptReason reason) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
238 assert(new_entry != 0, "only used for clone predicate");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
239 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
240 IfNode* iff = cont_proj->in(0)->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
241
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
242 ProjNode *uncommon_proj = iff->proj_out(1 - cont_proj->_con);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
243 Node *rgn = uncommon_proj->unique_ctrl_out();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
244 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
245
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
246 uint proj_index = 1; // region's edge corresponding to uncommon_proj
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
247 if (!rgn->is_Region()) { // create a region to guard the call
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
248 assert(rgn->is_Call(), "must be call uct");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
249 CallNode* call = rgn->as_Call();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
250 rgn = new (C, 1) RegionNode(1);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
251 register_new_node_with_optimizer(rgn);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
252 rgn->add_req(uncommon_proj);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
253 hash_delete(call);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
254 call->set_req(0, rgn);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
255 } else {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
256 // Find region's edge corresponding to uncommon_proj
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
257 for (; proj_index < rgn->req(); proj_index++)
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
258 if (rgn->in(proj_index) == uncommon_proj) break;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
259 assert(proj_index < rgn->req(), "sanity");
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
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
262 // Create new_iff in new location.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
263 IfNode *new_iff = iff->clone()->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
264 new_iff->set_req(0, new_entry);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
265
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
266 register_new_node_with_optimizer(new_iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
267 Node *if_cont = new (C, 1) IfTrueNode(new_iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
268 Node *if_uct = new (C, 1) IfFalseNode(new_iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
269 if (cont_proj->is_IfFalse()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
270 // Swap
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
271 Node* tmp = if_uct; if_uct = if_cont; if_cont = tmp;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
272 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
273 register_new_node_with_optimizer(if_cont);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
274 register_new_node_with_optimizer(if_uct);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
275
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
276 // if_uct to rgn
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
277 hash_delete(rgn);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
278 rgn->add_req(if_uct);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
279
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
280 // If rgn has phis add corresponding new edges which has the same
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
281 // value as on original uncommon_proj pass.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
282 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
283 bool has_phi = false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
284 for (DUIterator_Fast imax, i = rgn->fast_outs(imax); i < imax; i++) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
285 Node* use = rgn->fast_out(i);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
286 if (use->is_Phi() && use->outcnt() > 0) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
287 hash_delete(use);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
288 use->add_req(use->in(proj_index));
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
289 _worklist.push(use);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
290 has_phi = true;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
291 }
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 assert(!has_phi || rgn->req() > 3, "no phis when region is created");
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 return if_cont->as_Proj();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
296 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
297
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
298 //--------------------------clone_predicate-----------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
299 ProjNode* PhaseIdealLoop::clone_predicate(ProjNode* predicate_proj, Node* new_entry,
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
300 Deoptimization::DeoptReason reason,
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
301 PhaseIdealLoop* loop_phase,
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
302 PhaseIterGVN* igvn) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
303 ProjNode* new_predicate_proj;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
304 if (loop_phase != NULL) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
305 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
306 } else {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
307 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
308 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
309 IfNode* iff = new_predicate_proj->in(0)->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
310 Node* ctrl = iff->in(0);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
311
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
312 // Match original condition since predicate's projections could be swapped.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
313 assert(predicate_proj->in(0)->in(1)->in(1)->Opcode()==Op_Opaque1, "must be");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
314 Node* opq = new (igvn->C, 2) Opaque1Node(igvn->C, predicate_proj->in(0)->in(1)->in(1)->in(1));
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
315 igvn->C->add_predicate_opaq(opq);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
316
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
317 Node* bol = new (igvn->C, 2) Conv2BNode(opq);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
318 if (loop_phase != NULL) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
319 loop_phase->register_new_node(opq, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
320 loop_phase->register_new_node(bol, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
321 } else {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
322 igvn->register_new_node_with_optimizer(opq);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
323 igvn->register_new_node_with_optimizer(bol);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
324 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
325 igvn->hash_delete(iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
326 iff->set_req(1, bol);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
327 return new_predicate_proj;
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
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
330
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
331 //--------------------------clone_loop_predicates-----------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
332 // Interface from IGVN
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
333 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
334 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
335 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
336
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
337 // Interface from PhaseIdealLoop
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
338 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
339 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
340 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
341
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
342 // Clone loop predicates to cloned loops (peeled, unswitched, split_if).
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
343 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
344 bool clone_limit_check,
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
345 PhaseIdealLoop* loop_phase,
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
346 PhaseIterGVN* igvn) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
347 #ifdef ASSERT
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
348 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
349 if (new_entry != NULL)
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
350 new_entry->dump();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
351 assert(false, "not IfTrue, IfFalse, Region or SafePoint");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
352 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
353 #endif
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
354 // Search original predicates
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
355 Node* entry = old_entry;
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
356 ProjNode* limit_check_proj = NULL;
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
357 if (LoopLimitCheck) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
358 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
359 if (limit_check_proj != NULL) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
360 entry = entry->in(0)->in(0);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
361 }
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
362 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
363 if (UseLoopPredicate) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
364 ProjNode* predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
365 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
366 // clone predicate
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
367 new_entry = clone_predicate(predicate_proj, new_entry,
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
368 Deoptimization::Reason_predicate,
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
369 loop_phase, igvn);
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
370 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
371 if (TraceLoopPredicate) {
3845
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
372 tty->print("Loop Predicate cloned: ");
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
373 debug_only( new_entry->in(0)->dump(); )
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
374 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
375 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
376 }
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
377 if (limit_check_proj != NULL && clone_limit_check) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
378 // Clone loop limit check last to insert it before loop.
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
379 // Don't clone a limit check which was already finalized
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
380 // 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
381 new_entry = clone_predicate(limit_check_proj, new_entry,
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
382 Deoptimization::Reason_loop_limit_check,
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
383 loop_phase, igvn);
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
384 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
385 if (TraceLoopLimitCheck) {
3845
c96c3eb1efae 7068051: SIGSEGV in PhaseIdealLoop::build_loop_late_post
kvn
parents: 3840
diff changeset
386 tty->print("Loop Limit Check cloned: ");
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
387 debug_only( new_entry->in(0)->dump(); )
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
388 }
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
389 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
390 return new_entry;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
391 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
392
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
393 //--------------------------skip_loop_predicates------------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
394 // Skip related predicates.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
395 Node* PhaseIdealLoop::skip_loop_predicates(Node* entry) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
396 Node* predicate = NULL;
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
397 if (LoopLimitCheck) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
398 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
399 if (predicate != NULL) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
400 entry = entry->in(0)->in(0);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
401 }
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
402 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
403 if (UseLoopPredicate) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
404 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
405 if (predicate != NULL) { // right pattern that can be used by loop predication
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
406 IfNode* iff = entry->in(0)->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
407 ProjNode* uncommon_proj = iff->proj_out(1 - entry->as_Proj()->_con);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
408 Node* rgn = uncommon_proj->unique_ctrl_out();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
409 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
410 entry = entry->in(0)->in(0);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
411 while (entry != NULL && entry->is_Proj() && entry->in(0)->is_If()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
412 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
413 if (uncommon_proj->unique_ctrl_out() != rgn)
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
414 break;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
415 entry = entry->in(0)->in(0);
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 }
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 return entry;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
420 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
421
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
422 //--------------------------find_predicate_insertion_point-------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
423 // Find a good location to insert a predicate
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
424 ProjNode* PhaseIdealLoop::find_predicate_insertion_point(Node* start_c, Deoptimization::DeoptReason reason) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
425 if (start_c == NULL || !start_c->is_Proj())
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
426 return NULL;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
427 if (is_uncommon_trap_if_pattern(start_c->as_Proj(), reason)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
428 return start_c->as_Proj();
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 return NULL;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
431 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
432
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
433 //--------------------------find_predicate------------------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
434 // Find a predicate
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
435 Node* PhaseIdealLoop::find_predicate(Node* entry) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
436 Node* predicate = NULL;
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
437 if (LoopLimitCheck) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
438 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_loop_limit_check);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
439 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
440 return entry;
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
441 }
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
442 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
443 if (UseLoopPredicate) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
444 predicate = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
445 if (predicate != NULL) { // right pattern that can be used by loop predication
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
446 return entry;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
447 }
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 return NULL;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
450 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
451
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
452 //------------------------------Invariance-----------------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
453 // 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
454 // clone invariants.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
455 class Invariance : public StackObj {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
456 VectorSet _visited, _invariant;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
457 Node_Stack _stack;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
458 VectorSet _clone_visited;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
459 Node_List _old_new; // map of old to new (clone)
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
460 IdealLoopTree* _lpt;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
461 PhaseIdealLoop* _phase;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
462
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
463 // Helper function to set up the invariance for invariance computation
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
464 // 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
465 // the possibility to push n onto the stack for further processing.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
466 void visit(Node* use, Node* n) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
467 if (_lpt->is_invariant(n)) { // known invariant
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
468 _invariant.set(n->_idx);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
469 } else if (!n->is_CFG()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
470 Node *n_ctrl = _phase->ctrl_or_self(n);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
471 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
472 if (_phase->is_dominator(n_ctrl, u_ctrl)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
473 _stack.push(n, n->in(0) == NULL ? 1 : 0);
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 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
477
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
478 // Compute invariance for "the_node" and (possibly) all its inputs recursively
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
479 // on the fly
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
480 void compute_invariance(Node* n) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
481 assert(_visited.test(n->_idx), "must be");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
482 visit(n, n);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
483 while (_stack.is_nonempty()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
484 Node* n = _stack.node();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
485 uint idx = _stack.index();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
486 if (idx == n->req()) { // all inputs are processed
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
487 _stack.pop();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
488 // n is invariant if it's inputs are all invariant
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
489 bool all_inputs_invariant = true;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
490 for (uint i = 0; i < n->req(); i++) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
491 Node* in = n->in(i);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
492 if (in == NULL) continue;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
493 assert(_visited.test(in->_idx), "must have visited input");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
494 if (!_invariant.test(in->_idx)) { // bad guy
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
495 all_inputs_invariant = false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
496 break;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
497 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
498 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
499 if (all_inputs_invariant) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
500 _invariant.set(n->_idx); // I am a invariant too
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
501 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
502 } else { // process next input
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
503 _stack.set_index(idx + 1);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
504 Node* m = n->in(idx);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
505 if (m != NULL && !_visited.test_set(m->_idx)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
506 visit(n, m);
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 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
511
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
512 // Helper function to set up _old_new map for clone_nodes.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
513 // 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
514 // Otherwise, push n onto the stack for real cloning.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
515 void clone_visit(Node* n) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
516 assert(_invariant.test(n->_idx), "must be invariant");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
517 if (_lpt->is_invariant(n)) { // known invariant
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
518 _old_new.map(n->_idx, n);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
519 } else { // to be cloned
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
520 assert(!n->is_CFG(), "should not see CFG here");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
521 _stack.push(n, n->in(0) == NULL ? 1 : 0);
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 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
524
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
525 // Clone "n" and (possibly) all its inputs recursively
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
526 void clone_nodes(Node* n, Node* ctrl) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
527 clone_visit(n);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
528 while (_stack.is_nonempty()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
529 Node* n = _stack.node();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
530 uint idx = _stack.index();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
531 if (idx == n->req()) { // all inputs processed, clone n!
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
532 _stack.pop();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
533 // clone invariant node
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
534 Node* n_cl = n->clone();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
535 _old_new.map(n->_idx, n_cl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
536 _phase->register_new_node(n_cl, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
537 for (uint i = 0; i < n->req(); i++) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
538 Node* in = n_cl->in(i);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
539 if (in == NULL) continue;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
540 n_cl->set_req(i, _old_new[in->_idx]);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
541 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
542 } else { // process next input
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
543 _stack.set_index(idx + 1);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
544 Node* m = n->in(idx);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
545 if (m != NULL && !_clone_visited.test_set(m->_idx)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
546 clone_visit(m); // visit the input
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 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
551
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
552 public:
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
553 Invariance(Arena* area, IdealLoopTree* lpt) :
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
554 _lpt(lpt), _phase(lpt->_phase),
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
555 _visited(area), _invariant(area), _stack(area, 10 /* guess */),
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
556 _clone_visited(area), _old_new(area)
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
557 {}
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
558
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
559 // Map old to n for invariance computation and clone
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
560 void map_ctrl(Node* old, Node* n) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
561 assert(old->is_CFG() && n->is_CFG(), "must be");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
562 _old_new.map(old->_idx, n); // "clone" of old is n
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
563 _invariant.set(old->_idx); // old is invariant
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
564 _clone_visited.set(old->_idx);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
565 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
566
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
567 // Driver function to compute invariance
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
568 bool is_invariant(Node* n) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
569 if (!_visited.test_set(n->_idx))
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
570 compute_invariance(n);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
571 return (_invariant.test(n->_idx) != 0);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
572 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
573
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
574 // Driver function to clone invariant
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
575 Node* clone(Node* n, Node* ctrl) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
576 assert(ctrl->is_CFG(), "must be");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
577 assert(_invariant.test(n->_idx), "must be an invariant");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
578 if (!_clone_visited.test(n->_idx))
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
579 clone_nodes(n, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
580 return _old_new[n->_idx];
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 };
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
583
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
584 //------------------------------is_range_check_if -----------------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
585 // 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
586 // 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
587 // and offset to be loop invariant computed on the fly by "invar"
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
588 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
589 if (!is_loop_exit(iff)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
590 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
591 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
592 if (!iff->in(1)->is_Bool()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
593 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
594 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
595 const BoolNode *bol = iff->in(1)->as_Bool();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
596 if (bol->_test._test != BoolTest::lt) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
597 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
598 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
599 if (!bol->in(1)->is_Cmp()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
600 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
601 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
602 const CmpNode *cmp = bol->in(1)->as_Cmp();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
603 if (cmp->Opcode() != Op_CmpU) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
604 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
605 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
606 Node* range = cmp->in(2);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
607 if (range->Opcode() != Op_LoadRange) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
608 const TypeInt* tint = phase->_igvn.type(range)->isa_int();
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
609 if (tint == NULL || tint->empty() || tint->_lo < 0) {
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
610 // Allow predication on positive values that aren't LoadRanges.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
611 // This allows optimization of loops where the length of the
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
612 // 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
613 // from the array.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
614 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
615 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
616 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
617 if (!invar.is_invariant(range)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
618 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
619 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
620 Node *iv = _head->as_CountedLoop()->phi();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
621 int scale = 0;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
622 Node *offset = NULL;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
623 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
624 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
625 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
626 if (offset && !invar.is_invariant(offset)) { // offset must be invariant
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
627 return false;
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 return true;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
630 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
631
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
632 //------------------------------rc_predicate-----------------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
633 // Create a range check predicate
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
634 //
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
635 // for (i = init; i < limit; i += stride) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
636 // a[scale*i+offset]
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
637 // }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
638 //
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
639 // 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
640 // as "max(scale*i + offset) u< a.length".
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
641 //
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
642 // There are two cases for max(scale*i + offset):
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
643 // (1) stride*scale > 0
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
644 // max(scale*i + offset) = scale*(limit-stride) + offset
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
645 // (2) stride*scale < 0
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
646 // max(scale*i + offset) = scale*init + offset
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
647 BoolNode* PhaseIdealLoop::rc_predicate(IdealLoopTree *loop, Node* ctrl,
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
648 int scale, Node* offset,
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
649 Node* init, Node* limit, Node* stride,
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
650 Node* range, bool upper) {
3336
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
651 stringStream* predString = NULL;
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
652 if (TraceLoopPredicate) {
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
653 predString = new stringStream();
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
654 predString->print("rc_predicate ");
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
655 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
656
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
657 Node* max_idx_expr = init;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
658 int stride_con = stride->get_int();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
659 if ((stride_con > 0) == (scale > 0) == upper) {
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
660 if (LoopLimitCheck) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
661 // With LoopLimitCheck limit is not exact.
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
662 // Calculate exact limit here.
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
663 // Note, counted loop's test is '<' or '>'.
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
664 limit = exact_limit(loop);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
665 max_idx_expr = new (C, 3) SubINode(limit, stride);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
666 register_new_node(max_idx_expr, ctrl);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
667 if (TraceLoopPredicate) predString->print("(limit - stride) ");
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
668 } else {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
669 max_idx_expr = new (C, 3) SubINode(limit, stride);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
670 register_new_node(max_idx_expr, ctrl);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
671 if (TraceLoopPredicate) predString->print("(limit - stride) ");
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
672 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
673 } else {
3336
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
674 if (TraceLoopPredicate) predString->print("init ");
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
675 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
676
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
677 if (scale != 1) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
678 ConNode* con_scale = _igvn.intcon(scale);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
679 max_idx_expr = new (C, 3) MulINode(max_idx_expr, con_scale);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
680 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
681 if (TraceLoopPredicate) predString->print("* %d ", scale);
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
682 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
683
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
684 if (offset && (!offset->is_Con() || offset->get_int() != 0)){
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
685 max_idx_expr = new (C, 3) AddINode(max_idx_expr, offset);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
686 register_new_node(max_idx_expr, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
687 if (TraceLoopPredicate)
3336
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
688 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
689 else predString->print("+ offset ");
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
690 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
691
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
692 CmpUNode* cmp = new (C, 3) CmpUNode(max_idx_expr, range);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
693 register_new_node(cmp, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
694 BoolNode* bol = new (C, 2) BoolNode(cmp, BoolTest::lt);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
695 register_new_node(bol, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
696
3336
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
697 if (TraceLoopPredicate) {
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
698 predString->print_cr("<u range");
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
699 tty->print(predString->as_string());
2e038ad0c1d0 7009361: JSR 292 Invalid value on stack on solaris-sparc with -Xcomp
never
parents: 2445
diff changeset
700 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
701 return bol;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
702 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
703
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
704 //------------------------------ loop_predication_impl--------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
705 // Insert loop predicates for null checks and range checks
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
706 bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
707 if (!UseLoopPredicate) return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
708
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
709 if (!loop->_head->is_Loop()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
710 // Could be a simple region when irreducible loops are present.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
711 return false;
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 LoopNode* head = loop->_head->as_Loop();
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
714
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
715 if (head->unique_ctrl_out()->Opcode() == Op_NeverBranch) {
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
716 // do nothing for infinite loops
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
717 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
718 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
719
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
720 CountedLoopNode *cl = NULL;
3850
6987871cfb9b 7077439: Possible reference through NULL in loopPredicate.cpp:726
kvn
parents: 3845
diff changeset
721 if (head->is_valid_counted_loop()) {
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
722 cl = head->as_CountedLoop();
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
723 // do nothing for iteration-splitted loops
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
724 if (!cl->is_normal_loop()) return false;
3840
4e761e7e6e12 7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents: 3345
diff changeset
725 // Avoid RCE if Counted loop's test is '!='.
4e761e7e6e12 7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents: 3345
diff changeset
726 BoolTest::mask bt = cl->loopexit()->test_trip();
4e761e7e6e12 7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents: 3345
diff changeset
727 if (bt != BoolTest::lt && bt != BoolTest::gt)
4e761e7e6e12 7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents: 3345
diff changeset
728 cl = NULL;
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
729 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
730
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
731 Node* entry = head->in(LoopNode::EntryControl);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
732 ProjNode *predicate_proj = NULL;
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
733 // Loop limit check predicate should be near the loop.
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
734 if (LoopLimitCheck) {
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
735 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
736 if (predicate_proj != NULL)
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
737 entry = predicate_proj->in(0)->in(0);
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
738 }
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
739
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
740 predicate_proj = find_predicate_insertion_point(entry, Deoptimization::Reason_predicate);
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
741 if (!predicate_proj) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
742 #ifndef PRODUCT
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
743 if (TraceLoopPredicate) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
744 tty->print("missing predicate:");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
745 loop->dump_head();
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
746 head->dump(1);
2445
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
747 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
748 #endif
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
749 return false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
750 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
751 ConNode* zero = _igvn.intcon(0);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
752 set_ctrl(zero, C->root());
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
753
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
754 ResourceArea *area = Thread::current()->resource_area();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
755 Invariance invar(area, loop);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
756
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
757 // 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
758 // projs in the list, and they all dominate loop->tail()
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
759 Node_List if_proj_list(area);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
760 Node *current_proj = loop->tail(); //start from tail
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
761 while (current_proj != head) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
762 if (loop == get_loop(current_proj) && // still in the loop ?
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
763 current_proj->is_Proj() && // is a projection ?
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
764 current_proj->in(0)->Opcode() == Op_If) { // is a if projection ?
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
765 if_proj_list.push(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 current_proj = idom(current_proj);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
768 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
769
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
770 bool hoisted = false; // true if at least one proj is promoted
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
771 while (if_proj_list.size() > 0) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
772 // Following are changed to nonnull when a predicate can be hoisted
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
773 ProjNode* new_predicate_proj = NULL;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
774
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
775 ProjNode* proj = if_proj_list.pop()->as_Proj();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
776 IfNode* iff = proj->in(0)->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
777
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
778 if (!is_uncommon_trap_if_pattern(proj, Deoptimization::Reason_none)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
779 if (loop->is_loop_exit(iff)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
780 // 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
781 // depends on the condition of "iff" (iff->in(1)).
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
782 break;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
783 } else {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
784 // Both arms are inside the loop. There are two cases:
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
785 // (1) there is one backward branch. In this case, any remaining proj
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
786 // 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
787 // does not determine the execution the remining projs directly, and we
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
788 // can safely continue.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
789 // (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
790 // 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
791 continue;
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 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
794
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
795 Node* test = iff->in(1);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
796 if (!test->is_Bool()){ //Conv2B, ...
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
797 continue;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
798 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
799 BoolNode* bol = test->as_Bool();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
800 if (invar.is_invariant(bol)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
801 // Invariant test
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
802 new_predicate_proj = create_new_if_for_predicate(predicate_proj, NULL,
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
803 Deoptimization::Reason_predicate);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
804 Node* ctrl = new_predicate_proj->in(0)->as_If()->in(0);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
805 BoolNode* new_predicate_bol = invar.clone(bol, ctrl)->as_Bool();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
806
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
807 // Negate test if necessary
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
808 bool negated = false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
809 if (proj->_con != predicate_proj->_con) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
810 new_predicate_bol = new (C, 2) BoolNode(new_predicate_bol->in(1), new_predicate_bol->_test.negate());
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
811 register_new_node(new_predicate_bol, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
812 negated = true;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
813 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
814 IfNode* new_predicate_iff = new_predicate_proj->in(0)->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
815 _igvn.hash_delete(new_predicate_iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
816 new_predicate_iff->set_req(1, new_predicate_bol);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
817 #ifndef PRODUCT
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
818 if (TraceLoopPredicate) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
819 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
820 loop->dump_head();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
821 } else if (TraceLoopOpts) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
822 tty->print("Predicate IC ");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
823 loop->dump_head();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
824 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
825 #endif
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
826 } else if (cl != NULL && loop->is_range_check_if(iff, this, invar)) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
827 assert(proj->_con == predicate_proj->_con, "must match");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
828
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
829 // Range check for counted loops
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
830 const Node* cmp = bol->in(1)->as_Cmp();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
831 Node* idx = cmp->in(1);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
832 assert(!invar.is_invariant(idx), "index is variant");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
833 Node* rng = cmp->in(2);
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
834 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
835 assert(invar.is_invariant(rng), "range must be invariant");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
836 int scale = 1;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
837 Node* offset = zero;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
838 bool ok = is_scaled_iv_plus_offset(idx, cl->phi(), &scale, &offset);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
839 assert(ok, "must be index expression");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
840
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
841 Node* init = cl->init_trip();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
842 Node* limit = cl->limit();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
843 Node* stride = cl->stride();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
844
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
845 // Build if's for the upper and lower bound tests. The
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
846 // lower_bound test will dominate the upper bound test and all
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
847 // cloned or created nodes will use the lower bound test as
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
848 // their declared control.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
849 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
850 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
851 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
852 Node *ctrl = lower_bound_proj->in(0)->as_If()->in(0);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
853
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
854 // Perform cloning to keep Invariance state correct since the
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
855 // late schedule will place invariant things in the loop.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
856 rng = invar.clone(rng, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
857 if (offset && offset != zero) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
858 assert(invar.is_invariant(offset), "offset must be loop invariant");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
859 offset = invar.clone(offset, ctrl);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
860 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
861
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
862 // Test the lower bound
3345
bad7ecd0b6ed 5091921: Sign flip issues in loop optimizer
kvn
parents: 3336
diff changeset
863 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
864 IfNode* lower_bound_iff = lower_bound_proj->in(0)->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
865 _igvn.hash_delete(lower_bound_iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
866 lower_bound_iff->set_req(1, lower_bound_bol);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
867 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
868
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
869 // Test the upper bound
3840
4e761e7e6e12 7070134: Hotspot crashes with sigsegv from PorterStemmer
kvn
parents: 3345
diff changeset
870 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
871 IfNode* upper_bound_iff = upper_bound_proj->in(0)->as_If();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
872 _igvn.hash_delete(upper_bound_iff);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
873 upper_bound_iff->set_req(1, upper_bound_bol);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
874 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
875
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
876 // Fall through into rest of the clean up code which will move
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
877 // any dependent nodes onto the upper bound test.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
878 new_predicate_proj = upper_bound_proj;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
879
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
880 #ifndef PRODUCT
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
881 if (TraceLoopOpts && !TraceLoopPredicate) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
882 tty->print("Predicate RC ");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
883 loop->dump_head();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
884 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
885 #endif
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
886 } else {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
887 // Loop variant check (for example, range check in non-counted loop)
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
888 // with uncommon trap.
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
889 continue;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
890 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
891 assert(new_predicate_proj != NULL, "sanity");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
892 // Success - attach condition (new_predicate_bol) to predicate if
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
893 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
894
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
895 // Eliminate the old If in the loop body
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
896 dominated_by( new_predicate_proj, iff, proj->_con != new_predicate_proj->_con );
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
897
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
898 hoisted = true;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
899 C->set_major_progress();
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
900 } // end while
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
901
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
902 #ifndef PRODUCT
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
903 // report that the loop predication has been actually performed
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
904 // for this loop
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
905 if (TraceLoopPredicate && hoisted) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
906 tty->print("Loop Predication Performed:");
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
907 loop->dump_head();
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 #endif
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 return hoisted;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
912 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
913
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
914 //------------------------------loop_predication--------------------------------
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
915 // driver routine for loop predication optimization
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
916 bool IdealLoopTree::loop_predication( PhaseIdealLoop *phase) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
917 bool hoisted = false;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
918 // Recursively promote predicates
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
919 if (_child) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
920 hoisted = _child->loop_predication( phase);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
921 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
922
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
923 // self
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
924 if (!_irreducible && !tail()->is_top()) {
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
925 hoisted |= phase->loop_predication_impl(this);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
926 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
927
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
928 if (_next) { //sibling
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
929 hoisted |= _next->loop_predication( phase);
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
930 }
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
931
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
932 return hoisted;
08eb13460b3a 7004535: Clone loop predicate during loop unswitch
kvn
parents:
diff changeset
933 }