author | zmajo |
Tue, 30 Aug 2016 09:30:16 +0200 | |
changeset 41052 | 3362c4368286 |
parent 34204 | 5ad1ba3afecc |
permissions | -rw-r--r-- |
1 | 1 |
/* |
33628 | 2 |
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. |
1 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. |
|
8 |
* |
|
9 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
13 |
* accompanied this code). |
|
14 |
* |
|
15 |
* You should have received a copy of the GNU General Public License version |
|
16 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
17 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 |
* |
|
5547
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3919
diff
changeset
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3919
diff
changeset
|
20 |
* or visit www.oracle.com if you need additional information or have any |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3919
diff
changeset
|
21 |
* questions. |
1 | 22 |
* |
23 |
*/ |
|
24 |
||
7397 | 25 |
#ifndef SHARE_VM_OPTO_IDEALKIT_HPP |
26 |
#define SHARE_VM_OPTO_IDEALKIT_HPP |
|
27 |
||
28 |
#include "opto/addnode.hpp" |
|
29 |
#include "opto/cfgnode.hpp" |
|
23528 | 30 |
#include "opto/castnode.hpp" |
7397 | 31 |
#include "opto/connode.hpp" |
32 |
#include "opto/divnode.hpp" |
|
8732
16fc1c68714b
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
7397
diff
changeset
|
33 |
#include "opto/graphKit.hpp" |
7397 | 34 |
#include "opto/mulnode.hpp" |
35 |
#include "opto/phaseX.hpp" |
|
36 |
#include "opto/subnode.hpp" |
|
37 |
#include "opto/type.hpp" |
|
38 |
||
1 | 39 |
//----------------------------------------------------------------------------- |
40 |
//----------------------------IdealKit----------------------------------------- |
|
41 |
// Set of utilities for creating control flow and scalar SSA data flow. |
|
42 |
// Control: |
|
43 |
// if_then(left, relop, right) |
|
44 |
// else_ (optional) |
|
45 |
// end_if |
|
46 |
// loop(iv variable, initial, relop, limit) |
|
47 |
// - sets iv to initial for first trip |
|
48 |
// - exits when relation on limit is true |
|
49 |
// - the values of initial and limit should be loop invariant |
|
50 |
// - no increment, must be explicitly coded |
|
51 |
// - final value of iv is available after end_loop (until dead()) |
|
52 |
// end_loop |
|
53 |
// make_label(number of gotos) |
|
54 |
// goto_(label) |
|
55 |
// bind(label) |
|
56 |
// Data: |
|
57 |
// ConI(integer constant) - create an integer constant |
|
58 |
// set(variable, value) - assignment |
|
59 |
// value(variable) - reference value |
|
60 |
// dead(variable) - variable's value is no longer live |
|
61 |
// increment(variable, value) - increment variable by value |
|
62 |
// simple operations: AddI, SubI, AndI, LShiftI, etc. |
|
63 |
// Example: |
|
64 |
// Node* limit = ?? |
|
65 |
// IdealVariable i(kit), j(kit); |
|
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
1
diff
changeset
|
66 |
// declarations_done(); |
1 | 67 |
// Node* exit = make_label(1); // 1 goto |
68 |
// set(j, ConI(0)); |
|
69 |
// loop(i, ConI(0), BoolTest::lt, limit); { |
|
70 |
// if_then(value(i), BoolTest::gt, ConI(5)) { |
|
71 |
// set(j, ConI(1)); |
|
72 |
// goto_(exit); dead(i); |
|
73 |
// } end_if(); |
|
74 |
// increment(i, ConI(1)); |
|
75 |
// } end_loop(); dead(i); |
|
76 |
// bind(exit); |
|
77 |
// |
|
78 |
// See string_indexOf for a more complete example. |
|
79 |
||
80 |
class IdealKit; |
|
81 |
||
82 |
// Variable definition for IdealKit |
|
83 |
class IdealVariable: public StackObj { |
|
84 |
friend class IdealKit; |
|
85 |
private: |
|
86 |
int _id; |
|
87 |
void set_id(int id) { _id = id; } |
|
88 |
public: |
|
89 |
IdealVariable(IdealKit &k); |
|
90 |
int id() { assert(has_id(),"uninitialized id"); return _id; } |
|
91 |
bool has_id() { return _id >= 0; } |
|
92 |
}; |
|
93 |
||
94 |
class IdealKit: public StackObj { |
|
95 |
friend class IdealVariable; |
|
96 |
// The main state (called a cvstate for Control and Variables) |
|
97 |
// contains both the current values of the variables and the |
|
98 |
// current set of predecessor control edges. The variable values |
|
99 |
// are managed via a Node [in(1)..in(_var_ct)], and the predecessor |
|
100 |
// control edges managed via a RegionNode. The in(0) of the Node |
|
101 |
// for variables points to the RegionNode for the control edges. |
|
102 |
protected: |
|
103 |
Compile * const C; |
|
104 |
PhaseGVN &_gvn; |
|
105 |
GrowableArray<Node*>* _pending_cvstates; // stack of cvstates |
|
106 |
Node* _cvstate; // current cvstate (control, memory and variables) |
|
107 |
uint _var_ct; // number of variables |
|
108 |
bool _delay_all_transforms; // flag forcing all transforms to be delayed |
|
109 |
Node* _initial_ctrl; // saves initial control until variables declared |
|
110 |
Node* _initial_memory; // saves initial memory until variables declared |
|
9100
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
111 |
Node* _initial_i_o; // saves initial i_o until variables declared |
1 | 112 |
|
113 |
PhaseGVN& gvn() const { return _gvn; } |
|
114 |
// Create a new cvstate filled with nulls |
|
115 |
Node* new_cvstate(); // Create a new cvstate |
|
116 |
Node* cvstate() { return _cvstate; } // current cvstate |
|
117 |
Node* copy_cvstate(); // copy current cvstate |
|
118 |
||
119 |
void set_memory(Node* mem, uint alias_idx ); |
|
120 |
void do_memory_merge(Node* merging, Node* join); |
|
121 |
void clear(Node* m); // clear a cvstate |
|
122 |
void stop() { clear(_cvstate); } // clear current cvstate |
|
123 |
Node* delay_transform(Node* n); |
|
16619
a0e531dcc9e9
8004640: C2 assert failure in memnode.cpp: NULL+offs not RAW address
kvn
parents:
13963
diff
changeset
|
124 |
Node* transform(Node* n); // gvn.transform or skip it |
1 | 125 |
Node* promote_to_phi(Node* n, Node* reg);// Promote "n" to a phi on region "reg" |
126 |
bool was_promoted_to_phi(Node* n, Node* reg) { |
|
127 |
return (n->is_Phi() && n->in(0) == reg); |
|
128 |
} |
|
129 |
void declare(IdealVariable* v) { v->set_id(_var_ct++); } |
|
130 |
// This declares the position where vars are kept in the cvstate |
|
131 |
// For some degree of consistency we use the TypeFunc enum to |
|
132 |
// soak up spots in the inputs even though we only use early Control |
|
133 |
// and Memory slots. (So far.) |
|
134 |
static const uint first_var; // = TypeFunc::Parms + 1; |
|
135 |
||
136 |
#ifdef ASSERT |
|
137 |
enum State { NullS=0, BlockS=1, LoopS=2, IfThenS=4, ElseS=8, EndifS= 16 }; |
|
138 |
GrowableArray<int>* _state; |
|
139 |
State state() { return (State)(_state->top()); } |
|
140 |
#endif |
|
141 |
||
142 |
// Users should not care about slices only MergedMem so no access for them. |
|
143 |
Node* memory(uint alias_idx); |
|
144 |
||
145 |
public: |
|
9100
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
146 |
IdealKit(GraphKit* gkit, bool delay_all_transforms = false, bool has_declarations = false); |
1 | 147 |
~IdealKit() { |
148 |
stop(); |
|
149 |
} |
|
9100
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
150 |
void sync_kit(GraphKit* gkit); |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
151 |
|
1 | 152 |
// Control |
153 |
Node* ctrl() { return _cvstate->in(TypeFunc::Control); } |
|
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
1
diff
changeset
|
154 |
void set_ctrl(Node* ctrl) { _cvstate->set_req(TypeFunc::Control, ctrl); } |
1 | 155 |
Node* top() { return C->top(); } |
156 |
MergeMemNode* merged_memory() { return _cvstate->in(TypeFunc::Memory)->as_MergeMem(); } |
|
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
1
diff
changeset
|
157 |
void set_all_memory(Node* mem) { _cvstate->set_req(TypeFunc::Memory, mem); } |
9100
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
158 |
Node* i_o() { return _cvstate->in(TypeFunc::I_O); } |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
159 |
void set_i_o(Node* c) { _cvstate->set_req(TypeFunc::I_O, c); } |
1 | 160 |
void set(IdealVariable& v, Node* rhs) { _cvstate->set_req(first_var + v.id(), rhs); } |
161 |
Node* value(IdealVariable& v) { return _cvstate->in(first_var + v.id()); } |
|
162 |
void dead(IdealVariable& v) { set(v, (Node*)NULL); } |
|
163 |
void if_then(Node* left, BoolTest::mask relop, Node* right, |
|
164 |
float prob = PROB_FAIR, float cnt = COUNT_UNKNOWN, |
|
165 |
bool push_new_state = true); |
|
166 |
void else_(); |
|
167 |
void end_if(); |
|
8732
16fc1c68714b
7008866: Missing loop predicate for loop with multiple entries
kvn
parents:
7397
diff
changeset
|
168 |
void loop(GraphKit* gkit, int nargs, IdealVariable& iv, Node* init, BoolTest::mask cmp, Node* limit, |
1 | 169 |
float prob = PROB_LIKELY(0.9), float cnt = COUNT_UNKNOWN); |
170 |
void end_loop(); |
|
171 |
Node* make_label(int goto_ct); |
|
172 |
void bind(Node* lab); |
|
173 |
void goto_(Node* lab, bool bind = false); |
|
3268
f034e0c86895
6851742: (EA) allocation elimination doesn't work with UseG1GC
kvn
parents:
1
diff
changeset
|
174 |
void declarations_done(); |
1 | 175 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
176 |
Node* IfTrue(IfNode* iff) { return transform(new IfTrueNode(iff)); } |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
177 |
Node* IfFalse(IfNode* iff) { return transform(new IfFalseNode(iff)); } |
1 | 178 |
|
179 |
// Data |
|
180 |
Node* ConI(jint k) { return (Node*)gvn().intcon(k); } |
|
181 |
Node* makecon(const Type *t) const { return _gvn.makecon(t); } |
|
182 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
183 |
Node* AddI(Node* l, Node* r) { return transform(new AddINode(l, r)); } |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
184 |
Node* SubI(Node* l, Node* r) { return transform(new SubINode(l, r)); } |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
185 |
Node* AndI(Node* l, Node* r) { return transform(new AndINode(l, r)); } |
33628 | 186 |
Node* OrI(Node* l, Node* r) { return transform(new OrINode(l, r)); } |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
187 |
Node* MaxI(Node* l, Node* r) { return transform(new MaxINode(l, r)); } |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
188 |
Node* LShiftI(Node* l, Node* r) { return transform(new LShiftINode(l, r)); } |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
189 |
Node* CmpI(Node* l, Node* r) { return transform(new CmpINode(l, r)); } |
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
190 |
Node* Bool(Node* cmp, BoolTest::mask relop) { return transform(new BoolNode(cmp, relop)); } |
1 | 191 |
void increment(IdealVariable& v, Node* j) { set(v, AddI(value(v), j)); } |
192 |
void decrement(IdealVariable& v, Node* j) { set(v, SubI(value(v), j)); } |
|
193 |
||
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
194 |
Node* CmpL(Node* l, Node* r) { return transform(new CmpLNode(l, r)); } |
1 | 195 |
|
196 |
// TLS |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
197 |
Node* thread() { return gvn().transform(new ThreadLocalNode()); } |
1 | 198 |
|
199 |
// Pointers |
|
16619
a0e531dcc9e9
8004640: C2 assert failure in memnode.cpp: NULL+offs not RAW address
kvn
parents:
13963
diff
changeset
|
200 |
|
a0e531dcc9e9
8004640: C2 assert failure in memnode.cpp: NULL+offs not RAW address
kvn
parents:
13963
diff
changeset
|
201 |
// Raw address should be transformed regardless 'delay_transform' flag |
a0e531dcc9e9
8004640: C2 assert failure in memnode.cpp: NULL+offs not RAW address
kvn
parents:
13963
diff
changeset
|
202 |
// to produce canonical form CastX2P(offset). |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
203 |
Node* AddP(Node *base, Node *ptr, Node *off) { return _gvn.transform(new AddPNode(base, ptr, off)); } |
16619
a0e531dcc9e9
8004640: C2 assert failure in memnode.cpp: NULL+offs not RAW address
kvn
parents:
13963
diff
changeset
|
204 |
|
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
205 |
Node* CmpP(Node* l, Node* r) { return transform(new CmpPNode(l, r)); } |
1 | 206 |
#ifdef _LP64 |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
207 |
Node* XorX(Node* l, Node* r) { return transform(new XorLNode(l, r)); } |
1 | 208 |
#else // _LP64 |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
209 |
Node* XorX(Node* l, Node* r) { return transform(new XorINode(l, r)); } |
1 | 210 |
#endif // _LP64 |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
211 |
Node* URShiftX(Node* l, Node* r) { return transform(new URShiftXNode(l, r)); } |
1 | 212 |
Node* ConX(jint k) { return (Node*)gvn().MakeConX(k); } |
24923
9631f7d691dc
8034812: remove IDX_INIT macro hack in Node class
thartmann
parents:
23528
diff
changeset
|
213 |
Node* CastPX(Node* ctl, Node* p) { return transform(new CastP2XNode(ctl, p)); } |
1 | 214 |
|
215 |
// Memory operations |
|
216 |
||
217 |
// This is the base version which is given an alias index. |
|
218 |
Node* load(Node* ctl, |
|
219 |
Node* adr, |
|
220 |
const Type* t, |
|
221 |
BasicType bt, |
|
222 |
int adr_idx, |
|
223 |
bool require_atomic_access = false); |
|
224 |
||
225 |
// Return the new StoreXNode |
|
226 |
Node* store(Node* ctl, |
|
227 |
Node* adr, |
|
228 |
Node* val, |
|
229 |
BasicType bt, |
|
230 |
int adr_idx, |
|
22845
d8812d0ff387
8024921: PPC64 (part 113): Extend Load and Store nodes to know about memory ordering
goetz
parents:
16619
diff
changeset
|
231 |
MemNode::MemOrd mo, |
34157
4fde32e81092
8140309: [REDO] failed: no mismatched stores, except on raw memory: StoreB StoreI
roland
parents:
33628
diff
changeset
|
232 |
bool require_atomic_access = false, |
34204
5ad1ba3afecc
8140390: Char stores/loads accessing byte arrays must be marked as unmatched
thartmann
parents:
34157
diff
changeset
|
233 |
bool mismatched = false); |
1 | 234 |
|
235 |
// Store a card mark ordered after store_oop |
|
236 |
Node* storeCM(Node* ctl, |
|
237 |
Node* adr, |
|
238 |
Node* val, |
|
239 |
Node* oop_store, |
|
3904
007a45522a7f
6877254: Server vm crashes with no branches off of store slice" when run with CMS and UseSuperWord(default)
cfang
parents:
3268
diff
changeset
|
240 |
int oop_adr_idx, |
1 | 241 |
BasicType bt, |
242 |
int adr_idx); |
|
243 |
||
244 |
// Trivial call |
|
245 |
void make_leaf_call(const TypeFunc *slow_call_type, |
|
246 |
address slow_call, |
|
247 |
const char *leaf_name, |
|
248 |
Node* parm0, |
|
249 |
Node* parm1 = NULL, |
|
9100
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
250 |
Node* parm2 = NULL, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
251 |
Node* parm3 = NULL); |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
252 |
|
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
253 |
void make_leaf_call_no_fp(const TypeFunc *slow_call_type, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
254 |
address slow_call, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
255 |
const char *leaf_name, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
256 |
const TypePtr* adr_type, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
257 |
Node* parm0, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
258 |
Node* parm1, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
259 |
Node* parm2, |
860ba6f8b53f
7032314: Allow to generate CallLeafNoFPNode in IdealKit
kvn
parents:
8732
diff
changeset
|
260 |
Node* parm3); |
1 | 261 |
}; |
7397 | 262 |
|
263 |
#endif // SHARE_VM_OPTO_IDEALKIT_HPP |