Mercurial > hg > truffle
annotate src/share/vm/opto/superword.hpp @ 9126:bc26f978b0ce
HotSpotResolvedObjectType: implement hasFinalizeSubclass() correctly
don't use the (wrong) cached value, but ask the runtime on each request.
Fixes regression on xml.* benchmarks @ specjvm2008. The problem was:
After the constructor of Object was deoptimized due to an assumption violation,
it was recompiled again after some time. However, on recompilation, the value
of hasFinalizeSubclass for the class was not updated and it was compiled again
with a, now wrong, assumption, which then triggers deoptimization again.
This was repeated until it hit the recompilation limit (defined by
PerMethodRecompilationCutoff), and therefore only executed by the interpreter
from now on, causing the performance regression.
author | Bernhard Urban <bernhard.urban@jku.at> |
---|---|
date | Mon, 15 Apr 2013 19:54:58 +0200 |
parents | ad736b4683b4 |
children | de6a9e811145 |
rev | line source |
---|---|
0 | 1 /* |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
2 * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
21 * questions. |
0 | 22 */ |
23 | |
1972 | 24 #ifndef SHARE_VM_OPTO_SUPERWORD_HPP |
25 #define SHARE_VM_OPTO_SUPERWORD_HPP | |
26 | |
27 #include "opto/connode.hpp" | |
28 #include "opto/loopnode.hpp" | |
29 #include "opto/node.hpp" | |
30 #include "opto/phaseX.hpp" | |
31 #include "opto/vectornode.hpp" | |
32 #include "utilities/growableArray.hpp" | |
33 | |
0 | 34 // |
35 // S U P E R W O R D T R A N S F O R M | |
36 // | |
37 // SuperWords are short, fixed length vectors. | |
38 // | |
39 // Algorithm from: | |
40 // | |
41 // Exploiting SuperWord Level Parallelism with | |
42 // Multimedia Instruction Sets | |
43 // by | |
44 // Samuel Larsen and Saman Amarasighe | |
45 // MIT Laboratory for Computer Science | |
46 // date | |
47 // May 2000 | |
48 // published in | |
49 // ACM SIGPLAN Notices | |
50 // Proceedings of ACM PLDI '00, Volume 35 Issue 5 | |
51 // | |
52 // Definition 3.1 A Pack is an n-tuple, <s1, ...,sn>, where | |
53 // s1,...,sn are independent isomorphic statements in a basic | |
54 // block. | |
55 // | |
56 // Definition 3.2 A PackSet is a set of Packs. | |
57 // | |
58 // Definition 3.3 A Pair is a Pack of size two, where the | |
59 // first statement is considered the left element, and the | |
60 // second statement is considered the right element. | |
61 | |
62 class SWPointer; | |
63 class OrderedPair; | |
64 | |
65 // ========================= Dependence Graph ===================== | |
66 | |
67 class DepMem; | |
68 | |
69 //------------------------------DepEdge--------------------------- | |
70 // An edge in the dependence graph. The edges incident to a dependence | |
71 // node are threaded through _next_in for incoming edges and _next_out | |
72 // for outgoing edges. | |
73 class DepEdge : public ResourceObj { | |
74 protected: | |
75 DepMem* _pred; | |
76 DepMem* _succ; | |
77 DepEdge* _next_in; // list of in edges, null terminated | |
78 DepEdge* _next_out; // list of out edges, null terminated | |
79 | |
80 public: | |
81 DepEdge(DepMem* pred, DepMem* succ, DepEdge* next_in, DepEdge* next_out) : | |
82 _pred(pred), _succ(succ), _next_in(next_in), _next_out(next_out) {} | |
83 | |
84 DepEdge* next_in() { return _next_in; } | |
85 DepEdge* next_out() { return _next_out; } | |
86 DepMem* pred() { return _pred; } | |
87 DepMem* succ() { return _succ; } | |
88 | |
89 void print(); | |
90 }; | |
91 | |
92 //------------------------------DepMem--------------------------- | |
93 // A node in the dependence graph. _in_head starts the threaded list of | |
94 // incoming edges, and _out_head starts the list of outgoing edges. | |
95 class DepMem : public ResourceObj { | |
96 protected: | |
97 Node* _node; // Corresponding ideal node | |
98 DepEdge* _in_head; // Head of list of in edges, null terminated | |
99 DepEdge* _out_head; // Head of list of out edges, null terminated | |
100 | |
101 public: | |
102 DepMem(Node* node) : _node(node), _in_head(NULL), _out_head(NULL) {} | |
103 | |
104 Node* node() { return _node; } | |
105 DepEdge* in_head() { return _in_head; } | |
106 DepEdge* out_head() { return _out_head; } | |
107 void set_in_head(DepEdge* hd) { _in_head = hd; } | |
108 void set_out_head(DepEdge* hd) { _out_head = hd; } | |
109 | |
110 int in_cnt(); // Incoming edge count | |
111 int out_cnt(); // Outgoing edge count | |
112 | |
113 void print(); | |
114 }; | |
115 | |
116 //------------------------------DepGraph--------------------------- | |
117 class DepGraph VALUE_OBJ_CLASS_SPEC { | |
118 protected: | |
119 Arena* _arena; | |
120 GrowableArray<DepMem*> _map; | |
121 DepMem* _root; | |
122 DepMem* _tail; | |
123 | |
124 public: | |
125 DepGraph(Arena* a) : _arena(a), _map(a, 8, 0, NULL) { | |
126 _root = new (_arena) DepMem(NULL); | |
127 _tail = new (_arena) DepMem(NULL); | |
128 } | |
129 | |
130 DepMem* root() { return _root; } | |
131 DepMem* tail() { return _tail; } | |
132 | |
133 // Return dependence node corresponding to an ideal node | |
134 DepMem* dep(Node* node) { return _map.at(node->_idx); } | |
135 | |
136 // Make a new dependence graph node for an ideal node. | |
137 DepMem* make_node(Node* node); | |
138 | |
139 // Make a new dependence graph edge dprec->dsucc | |
140 DepEdge* make_edge(DepMem* dpred, DepMem* dsucc); | |
141 | |
142 DepEdge* make_edge(Node* pred, Node* succ) { return make_edge(dep(pred), dep(succ)); } | |
143 DepEdge* make_edge(DepMem* pred, Node* succ) { return make_edge(pred, dep(succ)); } | |
144 DepEdge* make_edge(Node* pred, DepMem* succ) { return make_edge(dep(pred), succ); } | |
145 | |
146 void init() { _map.clear(); } // initialize | |
147 | |
148 void print(Node* n) { dep(n)->print(); } | |
149 void print(DepMem* d) { d->print(); } | |
150 }; | |
151 | |
152 //------------------------------DepPreds--------------------------- | |
153 // Iterator over predecessors in the dependence graph and | |
154 // non-memory-graph inputs of ideal nodes. | |
155 class DepPreds : public StackObj { | |
156 private: | |
157 Node* _n; | |
158 int _next_idx, _end_idx; | |
159 DepEdge* _dep_next; | |
160 Node* _current; | |
161 bool _done; | |
162 | |
163 public: | |
164 DepPreds(Node* n, DepGraph& dg); | |
165 Node* current() { return _current; } | |
166 bool done() { return _done; } | |
167 void next(); | |
168 }; | |
169 | |
170 //------------------------------DepSuccs--------------------------- | |
171 // Iterator over successors in the dependence graph and | |
172 // non-memory-graph outputs of ideal nodes. | |
173 class DepSuccs : public StackObj { | |
174 private: | |
175 Node* _n; | |
176 int _next_idx, _end_idx; | |
177 DepEdge* _dep_next; | |
178 Node* _current; | |
179 bool _done; | |
180 | |
181 public: | |
182 DepSuccs(Node* n, DepGraph& dg); | |
183 Node* current() { return _current; } | |
184 bool done() { return _done; } | |
185 void next(); | |
186 }; | |
187 | |
188 | |
189 // ========================= SuperWord ===================== | |
190 | |
191 // -----------------------------SWNodeInfo--------------------------------- | |
192 // Per node info needed by SuperWord | |
193 class SWNodeInfo VALUE_OBJ_CLASS_SPEC { | |
194 public: | |
195 int _alignment; // memory alignment for a node | |
196 int _depth; // Max expression (DAG) depth from block start | |
197 const Type* _velt_type; // vector element type | |
198 Node_List* _my_pack; // pack containing this node | |
199 | |
200 SWNodeInfo() : _alignment(-1), _depth(0), _velt_type(NULL), _my_pack(NULL) {} | |
201 static const SWNodeInfo initial; | |
202 }; | |
203 | |
204 // -----------------------------SuperWord--------------------------------- | |
205 // Transforms scalar operations into packed (superword) operations. | |
206 class SuperWord : public ResourceObj { | |
207 private: | |
208 PhaseIdealLoop* _phase; | |
209 Arena* _arena; | |
210 PhaseIterGVN &_igvn; | |
211 | |
212 enum consts { top_align = -1, bottom_align = -666 }; | |
213 | |
214 GrowableArray<Node_List*> _packset; // Packs for the current block | |
215 | |
216 GrowableArray<int> _bb_idx; // Map from Node _idx to index within block | |
217 | |
218 GrowableArray<Node*> _block; // Nodes in current block | |
219 GrowableArray<Node*> _data_entry; // Nodes with all inputs from outside | |
220 GrowableArray<Node*> _mem_slice_head; // Memory slice head nodes | |
221 GrowableArray<Node*> _mem_slice_tail; // Memory slice tail nodes | |
222 | |
223 GrowableArray<SWNodeInfo> _node_info; // Info needed per node | |
224 | |
225 MemNode* _align_to_ref; // Memory reference that pre-loop will align to | |
226 | |
227 GrowableArray<OrderedPair> _disjoint_ptrs; // runtime disambiguated pointer pairs | |
228 | |
229 DepGraph _dg; // Dependence graph | |
230 | |
231 // Scratch pads | |
232 VectorSet _visited; // Visited set | |
233 VectorSet _post_visited; // Post-visited set | |
234 Node_Stack _n_idx_list; // List of (node,index) pairs | |
235 GrowableArray<Node*> _nlist; // List of nodes | |
236 GrowableArray<Node*> _stk; // Stack of nodes | |
237 | |
238 public: | |
239 SuperWord(PhaseIdealLoop* phase); | |
240 | |
241 void transform_loop(IdealLoopTree* lpt); | |
242 | |
243 // Accessors for SWPointer | |
244 PhaseIdealLoop* phase() { return _phase; } | |
245 IdealLoopTree* lpt() { return _lpt; } | |
246 PhiNode* iv() { return _iv; } | |
247 | |
248 private: | |
249 IdealLoopTree* _lpt; // Current loop tree node | |
250 LoopNode* _lp; // Current LoopNode | |
251 Node* _bb; // Current basic block | |
252 PhiNode* _iv; // Induction var | |
253 | |
254 // Accessors | |
255 Arena* arena() { return _arena; } | |
256 | |
257 Node* bb() { return _bb; } | |
258 void set_bb(Node* bb) { _bb = bb; } | |
259 | |
260 void set_lpt(IdealLoopTree* lpt) { _lpt = lpt; } | |
261 | |
262 LoopNode* lp() { return _lp; } | |
263 void set_lp(LoopNode* lp) { _lp = lp; | |
264 _iv = lp->as_CountedLoop()->phi()->as_Phi(); } | |
265 int iv_stride() { return lp()->as_CountedLoop()->stride_con(); } | |
266 | |
6183
6f8f439e247d
7177923: SIGBUS on sparc in compiled code for java.util.Calendar.clear()
kvn
parents:
6179
diff
changeset
|
267 int vector_width(Node* n) { |
6f8f439e247d
7177923: SIGBUS on sparc in compiled code for java.util.Calendar.clear()
kvn
parents:
6179
diff
changeset
|
268 BasicType bt = velt_basic_type(n); |
6f8f439e247d
7177923: SIGBUS on sparc in compiled code for java.util.Calendar.clear()
kvn
parents:
6179
diff
changeset
|
269 return MIN2(ABS(iv_stride()), Matcher::max_vector_size(bt)); |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
270 } |
6183
6f8f439e247d
7177923: SIGBUS on sparc in compiled code for java.util.Calendar.clear()
kvn
parents:
6179
diff
changeset
|
271 int vector_width_in_bytes(Node* n) { |
6f8f439e247d
7177923: SIGBUS on sparc in compiled code for java.util.Calendar.clear()
kvn
parents:
6179
diff
changeset
|
272 BasicType bt = velt_basic_type(n); |
6f8f439e247d
7177923: SIGBUS on sparc in compiled code for java.util.Calendar.clear()
kvn
parents:
6179
diff
changeset
|
273 return vector_width(n)*type2aelembytes(bt); |
6f8f439e247d
7177923: SIGBUS on sparc in compiled code for java.util.Calendar.clear()
kvn
parents:
6179
diff
changeset
|
274 } |
0 | 275 MemNode* align_to_ref() { return _align_to_ref; } |
276 void set_align_to_ref(MemNode* m) { _align_to_ref = m; } | |
277 | |
278 Node* ctrl(Node* n) const { return _phase->has_ctrl(n) ? _phase->get_ctrl(n) : n; } | |
279 | |
280 // block accessors | |
281 bool in_bb(Node* n) { return n != NULL && n->outcnt() > 0 && ctrl(n) == _bb; } | |
282 int bb_idx(Node* n) { assert(in_bb(n), "must be"); return _bb_idx.at(n->_idx); } | |
283 void set_bb_idx(Node* n, int i) { _bb_idx.at_put_grow(n->_idx, i); } | |
284 | |
285 // visited set accessors | |
286 void visited_clear() { _visited.Clear(); } | |
287 void visited_set(Node* n) { return _visited.set(bb_idx(n)); } | |
288 int visited_test(Node* n) { return _visited.test(bb_idx(n)); } | |
289 int visited_test_set(Node* n) { return _visited.test_set(bb_idx(n)); } | |
290 void post_visited_clear() { _post_visited.Clear(); } | |
291 void post_visited_set(Node* n) { return _post_visited.set(bb_idx(n)); } | |
292 int post_visited_test(Node* n) { return _post_visited.test(bb_idx(n)); } | |
293 | |
294 // Ensure node_info contains element "i" | |
295 void grow_node_info(int i) { if (i >= _node_info.length()) _node_info.at_put_grow(i, SWNodeInfo::initial); } | |
296 | |
297 // memory alignment for a node | |
298 int alignment(Node* n) { return _node_info.adr_at(bb_idx(n))->_alignment; } | |
299 void set_alignment(Node* n, int a) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_alignment = a; } | |
300 | |
301 // Max expression (DAG) depth from beginning of the block for each node | |
302 int depth(Node* n) { return _node_info.adr_at(bb_idx(n))->_depth; } | |
303 void set_depth(Node* n, int d) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_depth = d; } | |
304 | |
305 // vector element type | |
306 const Type* velt_type(Node* n) { return _node_info.adr_at(bb_idx(n))->_velt_type; } | |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
307 BasicType velt_basic_type(Node* n) { return velt_type(n)->array_element_basic_type(); } |
0 | 308 void set_velt_type(Node* n, const Type* t) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_velt_type = t; } |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
309 bool same_velt_type(Node* n1, Node* n2); |
0 | 310 |
311 // my_pack | |
312 Node_List* my_pack(Node* n) { return !in_bb(n) ? NULL : _node_info.adr_at(bb_idx(n))->_my_pack; } | |
313 void set_my_pack(Node* n, Node_List* p) { int i = bb_idx(n); grow_node_info(i); _node_info.adr_at(i)->_my_pack = p; } | |
314 | |
315 // methods | |
316 | |
317 // Extract the superword level parallelism | |
318 void SLP_extract(); | |
319 // Find the adjacent memory references and create pack pairs for them. | |
320 void find_adjacent_refs(); | |
321 // Find a memory reference to align the loop induction variable to. | |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
322 MemNode* find_align_to_ref(Node_List &memops); |
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
323 // Calculate loop's iv adjustment for this memory ops. |
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
324 int get_iv_adjustment(MemNode* mem); |
0 | 325 // Can the preloop align the reference to position zero in the vector? |
326 bool ref_is_alignable(SWPointer& p); | |
327 // Construct dependency graph. | |
328 void dependence_graph(); | |
329 // Return a memory slice (node list) in predecessor order starting at "start" | |
330 void mem_slice_preds(Node* start, Node* stop, GrowableArray<Node*> &preds); | |
605 | 331 // Can s1 and s2 be in a pack with s1 immediately preceding s2 and s1 aligned at "align" |
0 | 332 bool stmts_can_pack(Node* s1, Node* s2, int align); |
333 // Does s exist in a pack at position pos? | |
334 bool exists_at(Node* s, uint pos); | |
335 // Is s1 immediately before s2 in memory? | |
336 bool are_adjacent_refs(Node* s1, Node* s2); | |
337 // Are s1 and s2 similar? | |
338 bool isomorphic(Node* s1, Node* s2); | |
339 // Is there no data path from s1 to s2 or s2 to s1? | |
340 bool independent(Node* s1, Node* s2); | |
341 // Helper for independent | |
342 bool independent_path(Node* shallow, Node* deep, uint dp=0); | |
343 void set_alignment(Node* s1, Node* s2, int align); | |
344 int data_size(Node* s); | |
345 // Extend packset by following use->def and def->use links from pack members. | |
346 void extend_packlist(); | |
347 // Extend the packset by visiting operand definitions of nodes in pack p | |
348 bool follow_use_defs(Node_List* p); | |
349 // Extend the packset by visiting uses of nodes in pack p | |
350 bool follow_def_uses(Node_List* p); | |
351 // Estimate the savings from executing s1 and s2 as a pack | |
352 int est_savings(Node* s1, Node* s2); | |
353 int adjacent_profit(Node* s1, Node* s2); | |
354 int pack_cost(int ct); | |
355 int unpack_cost(int ct); | |
356 // Combine packs A and B with A.last == B.first into A.first..,A.last,B.second,..B.last | |
357 void combine_packs(); | |
358 // Construct the map from nodes to packs. | |
359 void construct_my_pack_map(); | |
360 // Remove packs that are not implemented or not profitable. | |
361 void filter_packs(); | |
362 // Adjust the memory graph for the packed operations | |
363 void schedule(); | |
667 | 364 // Remove "current" from its current position in the memory graph and insert |
365 // it after the appropriate insert points (lip or uip); | |
366 void remove_and_insert(MemNode *current, MemNode *prev, MemNode *lip, Node *uip, Unique_Node_List &schd_before); | |
367 // Within a store pack, schedule stores together by moving out the sandwiched memory ops according | |
368 // to dependence info; and within a load pack, move loads down to the last executed load. | |
0 | 369 void co_locate_pack(Node_List* p); |
370 // Convert packs into vector node operations | |
371 void output(); | |
372 // Create a vector operand for the nodes in pack p for operand: in(opd_idx) | |
3842 | 373 Node* vector_opd(Node_List* p, int opd_idx); |
0 | 374 // Can code be generated for pack p? |
375 bool implemented(Node_List* p); | |
376 // For pack p, are all operands and all uses (with in the block) vector? | |
377 bool profitable(Node_List* p); | |
378 // If a use of pack p is not a vector use, then replace the use with an extract operation. | |
379 void insert_extracts(Node_List* p); | |
380 // Is use->in(u_idx) a vector use? | |
381 bool is_vector_use(Node* use, int u_idx); | |
382 // Construct reverse postorder list of block members | |
8079
ad736b4683b4
8004867: VM crashing with assert "share/vm/opto/node.hpp:357 - assert(i < _max) failed: oob"
kvn
parents:
6794
diff
changeset
|
383 bool construct_bb(); |
0 | 384 // Initialize per node info |
385 void initialize_bb(); | |
386 // Insert n into block after pos | |
387 void bb_insert_after(Node* n, int pos); | |
388 // Compute max depth for expressions from beginning of block | |
389 void compute_max_depth(); | |
390 // Compute necessary vector element type for expressions | |
391 void compute_vector_element_type(); | |
392 // Are s1 and s2 in a pack pair and ordered as s1,s2? | |
393 bool in_packset(Node* s1, Node* s2); | |
394 // Is s in pack p? | |
395 Node_List* in_pack(Node* s, Node_List* p); | |
396 // Remove the pack at position pos in the packset | |
397 void remove_pack_at(int pos); | |
398 // Return the node executed first in pack p. | |
399 Node* executed_first(Node_List* p); | |
400 // Return the node executed last in pack p. | |
401 Node* executed_last(Node_List* p); | |
402 // Alignment within a vector memory reference | |
6794 | 403 int memory_alignment(MemNode* s, int iv_adjust); |
0 | 404 // (Start, end] half-open range defining which operands are vector |
405 void vector_opd_range(Node* n, uint* start, uint* end); | |
406 // Smallest type containing range of values | |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
407 const Type* container_type(Node* n); |
0 | 408 // Adjust pre-loop limit so that in main loop, a load/store reference |
409 // to align_to_ref will be a position zero in the vector. | |
410 void align_initial_loop_index(MemNode* align_to_ref); | |
411 // Find pre loop end from main loop. Returns null if none. | |
412 CountedLoopEndNode* get_pre_loop_end(CountedLoopNode *cl); | |
413 // Is the use of d1 in u1 at the same operand position as d2 in u2? | |
414 bool opnd_positions_match(Node* d1, Node* u1, Node* d2, Node* u2); | |
415 void init(); | |
416 | |
417 // print methods | |
418 void print_packset(); | |
419 void print_pack(Node_List* p); | |
420 void print_bb(); | |
421 void print_stmt(Node* s); | |
422 char* blank(uint depth); | |
423 }; | |
424 | |
425 | |
426 //------------------------------SWPointer--------------------------- | |
427 // Information about an address for dependence checking and vector alignment | |
428 class SWPointer VALUE_OBJ_CLASS_SPEC { | |
429 protected: | |
430 MemNode* _mem; // My memory reference node | |
431 SuperWord* _slp; // SuperWord class | |
432 | |
433 Node* _base; // NULL if unsafe nonheap reference | |
434 Node* _adr; // address pointer | |
435 jint _scale; // multipler for iv (in bytes), 0 if no loop iv | |
436 jint _offset; // constant offset (in bytes) | |
437 Node* _invar; // invariant offset (in bytes), NULL if none | |
438 bool _negate_invar; // if true then use: (0 - _invar) | |
439 | |
440 PhaseIdealLoop* phase() { return _slp->phase(); } | |
441 IdealLoopTree* lpt() { return _slp->lpt(); } | |
442 PhiNode* iv() { return _slp->iv(); } // Induction var | |
443 | |
444 bool invariant(Node* n) { | |
445 Node *n_c = phase()->get_ctrl(n); | |
446 return !lpt()->is_member(phase()->get_loop(n_c)); | |
447 } | |
448 | |
449 // Match: k*iv + offset | |
450 bool scaled_iv_plus_offset(Node* n); | |
451 // Match: k*iv where k is a constant that's not zero | |
452 bool scaled_iv(Node* n); | |
453 // Match: offset is (k [+/- invariant]) | |
454 bool offset_plus_k(Node* n, bool negate = false); | |
455 | |
456 public: | |
457 enum CMP { | |
458 Less = 1, | |
459 Greater = 2, | |
460 Equal = 4, | |
461 NotEqual = (Less | Greater), | |
462 NotComparable = (Less | Greater | Equal) | |
463 }; | |
464 | |
465 SWPointer(MemNode* mem, SuperWord* slp); | |
466 // Following is used to create a temporary object during | |
467 // the pattern match of an address expression. | |
468 SWPointer(SWPointer* p); | |
469 | |
470 bool valid() { return _adr != NULL; } | |
471 bool has_iv() { return _scale != 0; } | |
472 | |
473 Node* base() { return _base; } | |
474 Node* adr() { return _adr; } | |
6179
8c92982cbbc4
7119644: Increase superword's vector size up to 256 bits
kvn
parents:
3842
diff
changeset
|
475 MemNode* mem() { return _mem; } |
0 | 476 int scale_in_bytes() { return _scale; } |
477 Node* invar() { return _invar; } | |
478 bool negate_invar() { return _negate_invar; } | |
479 int offset_in_bytes() { return _offset; } | |
480 int memory_size() { return _mem->memory_size(); } | |
481 | |
482 // Comparable? | |
483 int cmp(SWPointer& q) { | |
484 if (valid() && q.valid() && | |
485 (_adr == q._adr || _base == _adr && q._base == q._adr) && | |
486 _scale == q._scale && | |
487 _invar == q._invar && | |
488 _negate_invar == q._negate_invar) { | |
489 bool overlap = q._offset < _offset + memory_size() && | |
490 _offset < q._offset + q.memory_size(); | |
491 return overlap ? Equal : (_offset < q._offset ? Less : Greater); | |
492 } else { | |
493 return NotComparable; | |
494 } | |
495 } | |
496 | |
497 bool not_equal(SWPointer& q) { return not_equal(cmp(q)); } | |
498 bool equal(SWPointer& q) { return equal(cmp(q)); } | |
499 bool comparable(SWPointer& q) { return comparable(cmp(q)); } | |
500 static bool not_equal(int cmp) { return cmp <= NotEqual; } | |
501 static bool equal(int cmp) { return cmp == Equal; } | |
502 static bool comparable(int cmp) { return cmp < NotComparable; } | |
503 | |
504 void print(); | |
505 }; | |
506 | |
507 | |
508 //------------------------------OrderedPair--------------------------- | |
509 // Ordered pair of Node*. | |
510 class OrderedPair VALUE_OBJ_CLASS_SPEC { | |
511 protected: | |
512 Node* _p1; | |
513 Node* _p2; | |
514 public: | |
515 OrderedPair() : _p1(NULL), _p2(NULL) {} | |
516 OrderedPair(Node* p1, Node* p2) { | |
517 if (p1->_idx < p2->_idx) { | |
518 _p1 = p1; _p2 = p2; | |
519 } else { | |
520 _p1 = p2; _p2 = p1; | |
521 } | |
522 } | |
523 | |
524 bool operator==(const OrderedPair &rhs) { | |
525 return _p1 == rhs._p1 && _p2 == rhs._p2; | |
526 } | |
527 void print() { tty->print(" (%d, %d)", _p1->_idx, _p2->_idx); } | |
528 | |
529 static const OrderedPair initial; | |
530 }; | |
1972 | 531 |
532 #endif // SHARE_VM_OPTO_SUPERWORD_HPP |