Mercurial > hg > truffle
annotate src/share/vm/adlc/formssel.cpp @ 1721:413ad0331a0c
6977924: Changes for 6975078 produce build error with certain gcc versions
Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error.
Reviewed-by: jcoomes, ysr, phh
author | johnc |
---|---|
date | Wed, 18 Aug 2010 10:59:06 -0700 |
parents | c18cbe5936b8 |
children | 2f644f85485d |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1541
diff
changeset
|
2 * Copyright (c) 1998, 2010, 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:
1541
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
1541
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:
1541
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 // FORMS.CPP - Definitions for ADL Parser Forms Classes | |
26 #include "adlc.hpp" | |
27 | |
28 //==============================Instructions=================================== | |
29 //------------------------------InstructForm----------------------------------- | |
30 InstructForm::InstructForm(const char *id, bool ideal_only) | |
31 : _ident(id), _ideal_only(ideal_only), | |
32 _localNames(cmpstr, hashstr, Form::arena), | |
33 _effects(cmpstr, hashstr, Form::arena) { | |
34 _ftype = Form::INS; | |
35 | |
36 _matrule = NULL; | |
37 _insencode = NULL; | |
38 _opcode = NULL; | |
39 _size = NULL; | |
40 _attribs = NULL; | |
41 _predicate = NULL; | |
42 _exprule = NULL; | |
43 _rewrule = NULL; | |
44 _format = NULL; | |
45 _peephole = NULL; | |
46 _ins_pipe = NULL; | |
47 _uniq_idx = NULL; | |
48 _num_uniq = 0; | |
49 _cisc_spill_operand = Not_cisc_spillable;// Which operand may cisc-spill | |
50 _cisc_spill_alternate = NULL; // possible cisc replacement | |
51 _cisc_reg_mask_name = NULL; | |
52 _is_cisc_alternate = false; | |
53 _is_short_branch = false; | |
54 _short_branch_form = NULL; | |
55 _alignment = 1; | |
56 } | |
57 | |
58 InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule) | |
59 : _ident(id), _ideal_only(false), | |
60 _localNames(instr->_localNames), | |
61 _effects(instr->_effects) { | |
62 _ftype = Form::INS; | |
63 | |
64 _matrule = rule; | |
65 _insencode = instr->_insencode; | |
66 _opcode = instr->_opcode; | |
67 _size = instr->_size; | |
68 _attribs = instr->_attribs; | |
69 _predicate = instr->_predicate; | |
70 _exprule = instr->_exprule; | |
71 _rewrule = instr->_rewrule; | |
72 _format = instr->_format; | |
73 _peephole = instr->_peephole; | |
74 _ins_pipe = instr->_ins_pipe; | |
75 _uniq_idx = instr->_uniq_idx; | |
76 _num_uniq = instr->_num_uniq; | |
77 _cisc_spill_operand = Not_cisc_spillable;// Which operand may cisc-spill | |
78 _cisc_spill_alternate = NULL; // possible cisc replacement | |
79 _cisc_reg_mask_name = NULL; | |
80 _is_cisc_alternate = false; | |
81 _is_short_branch = false; | |
82 _short_branch_form = NULL; | |
83 _alignment = 1; | |
84 // Copy parameters | |
85 const char *name; | |
86 instr->_parameters.reset(); | |
87 for (; (name = instr->_parameters.iter()) != NULL;) | |
88 _parameters.addName(name); | |
89 } | |
90 | |
91 InstructForm::~InstructForm() { | |
92 } | |
93 | |
94 InstructForm *InstructForm::is_instruction() const { | |
95 return (InstructForm*)this; | |
96 } | |
97 | |
98 bool InstructForm::ideal_only() const { | |
99 return _ideal_only; | |
100 } | |
101 | |
102 bool InstructForm::sets_result() const { | |
103 return (_matrule != NULL && _matrule->sets_result()); | |
104 } | |
105 | |
106 bool InstructForm::needs_projections() { | |
107 _components.reset(); | |
108 for( Component *comp; (comp = _components.iter()) != NULL; ) { | |
109 if (comp->isa(Component::KILL)) { | |
110 return true; | |
111 } | |
112 } | |
113 return false; | |
114 } | |
115 | |
116 | |
117 bool InstructForm::has_temps() { | |
118 if (_matrule) { | |
119 // Examine each component to see if it is a TEMP | |
120 _components.reset(); | |
121 // Skip the first component, if already handled as (SET dst (...)) | |
122 Component *comp = NULL; | |
123 if (sets_result()) comp = _components.iter(); | |
124 while ((comp = _components.iter()) != NULL) { | |
125 if (comp->isa(Component::TEMP)) { | |
126 return true; | |
127 } | |
128 } | |
129 } | |
130 | |
131 return false; | |
132 } | |
133 | |
134 uint InstructForm::num_defs_or_kills() { | |
135 uint defs_or_kills = 0; | |
136 | |
137 _components.reset(); | |
138 for( Component *comp; (comp = _components.iter()) != NULL; ) { | |
139 if( comp->isa(Component::DEF) || comp->isa(Component::KILL) ) { | |
140 ++defs_or_kills; | |
141 } | |
142 } | |
143 | |
144 return defs_or_kills; | |
145 } | |
146 | |
147 // This instruction has an expand rule? | |
148 bool InstructForm::expands() const { | |
149 return ( _exprule != NULL ); | |
150 } | |
151 | |
152 // This instruction has a peephole rule? | |
153 Peephole *InstructForm::peepholes() const { | |
154 return _peephole; | |
155 } | |
156 | |
157 // This instruction has a peephole rule? | |
158 void InstructForm::append_peephole(Peephole *peephole) { | |
159 if( _peephole == NULL ) { | |
160 _peephole = peephole; | |
161 } else { | |
162 _peephole->append_peephole(peephole); | |
163 } | |
164 } | |
165 | |
166 | |
167 // ideal opcode enumeration | |
168 const char *InstructForm::ideal_Opcode( FormDict &globalNames ) const { | |
169 if( !_matrule ) return "Node"; // Something weird | |
170 // Chain rules do not really have ideal Opcodes; use their source | |
171 // operand ideal Opcode instead. | |
172 if( is_simple_chain_rule(globalNames) ) { | |
173 const char *src = _matrule->_rChild->_opType; | |
174 OperandForm *src_op = globalNames[src]->is_operand(); | |
175 assert( src_op, "Not operand class of chain rule" ); | |
176 if( !src_op->_matrule ) return "Node"; | |
177 return src_op->_matrule->_opType; | |
178 } | |
179 // Operand chain rules do not really have ideal Opcodes | |
180 if( _matrule->is_chain_rule(globalNames) ) | |
181 return "Node"; | |
182 return strcmp(_matrule->_opType,"Set") | |
183 ? _matrule->_opType | |
184 : _matrule->_rChild->_opType; | |
185 } | |
186 | |
187 // Recursive check on all operands' match rules in my match rule | |
188 bool InstructForm::is_pinned(FormDict &globals) { | |
189 if ( ! _matrule) return false; | |
190 | |
191 int index = 0; | |
192 if (_matrule->find_type("Goto", index)) return true; | |
193 if (_matrule->find_type("If", index)) return true; | |
194 if (_matrule->find_type("CountedLoopEnd",index)) return true; | |
195 if (_matrule->find_type("Return", index)) return true; | |
196 if (_matrule->find_type("Rethrow", index)) return true; | |
197 if (_matrule->find_type("TailCall", index)) return true; | |
198 if (_matrule->find_type("TailJump", index)) return true; | |
199 if (_matrule->find_type("Halt", index)) return true; | |
200 if (_matrule->find_type("Jump", index)) return true; | |
201 | |
202 return is_parm(globals); | |
203 } | |
204 | |
205 // Recursive check on all operands' match rules in my match rule | |
206 bool InstructForm::is_projection(FormDict &globals) { | |
207 if ( ! _matrule) return false; | |
208 | |
209 int index = 0; | |
210 if (_matrule->find_type("Goto", index)) return true; | |
211 if (_matrule->find_type("Return", index)) return true; | |
212 if (_matrule->find_type("Rethrow", index)) return true; | |
213 if (_matrule->find_type("TailCall",index)) return true; | |
214 if (_matrule->find_type("TailJump",index)) return true; | |
215 if (_matrule->find_type("Halt", index)) return true; | |
216 | |
217 return false; | |
218 } | |
219 | |
220 // Recursive check on all operands' match rules in my match rule | |
221 bool InstructForm::is_parm(FormDict &globals) { | |
222 if ( ! _matrule) return false; | |
223 | |
224 int index = 0; | |
225 if (_matrule->find_type("Parm",index)) return true; | |
226 | |
227 return false; | |
228 } | |
229 | |
230 | |
231 // Return 'true' if this instruction matches an ideal 'Copy*' node | |
232 int InstructForm::is_ideal_copy() const { | |
233 return _matrule ? _matrule->is_ideal_copy() : 0; | |
234 } | |
235 | |
236 // Return 'true' if this instruction is too complex to rematerialize. | |
237 int InstructForm::is_expensive() const { | |
238 // We can prove it is cheap if it has an empty encoding. | |
239 // This helps with platform-specific nops like ThreadLocal and RoundFloat. | |
240 if (is_empty_encoding()) | |
241 return 0; | |
242 | |
243 if (is_tls_instruction()) | |
244 return 1; | |
245 | |
246 if (_matrule == NULL) return 0; | |
247 | |
248 return _matrule->is_expensive(); | |
249 } | |
250 | |
251 // Has an empty encoding if _size is a constant zero or there | |
252 // are no ins_encode tokens. | |
253 int InstructForm::is_empty_encoding() const { | |
254 if (_insencode != NULL) { | |
255 _insencode->reset(); | |
256 if (_insencode->encode_class_iter() == NULL) { | |
257 return 1; | |
258 } | |
259 } | |
260 if (_size != NULL && strcmp(_size, "0") == 0) { | |
261 return 1; | |
262 } | |
263 return 0; | |
264 } | |
265 | |
266 int InstructForm::is_tls_instruction() const { | |
267 if (_ident != NULL && | |
268 ( ! strcmp( _ident,"tlsLoadP") || | |
269 ! strncmp(_ident,"tlsLoadP_",9)) ) { | |
270 return 1; | |
271 } | |
272 | |
273 if (_matrule != NULL && _insencode != NULL) { | |
274 const char* opType = _matrule->_opType; | |
275 if (strcmp(opType, "Set")==0) | |
276 opType = _matrule->_rChild->_opType; | |
277 if (strcmp(opType,"ThreadLocal")==0) { | |
278 fprintf(stderr, "Warning: ThreadLocal instruction %s should be named 'tlsLoadP_*'\n", | |
279 (_ident == NULL ? "NULL" : _ident)); | |
280 return 1; | |
281 } | |
282 } | |
283 | |
284 return 0; | |
285 } | |
286 | |
287 | |
288 // Return 'true' if this instruction matches an ideal 'Copy*' node | |
289 bool InstructForm::is_ideal_unlock() const { | |
290 return _matrule ? _matrule->is_ideal_unlock() : false; | |
291 } | |
292 | |
293 bool InstructForm::is_ideal_call_leaf() const { | |
294 return _matrule ? _matrule->is_ideal_call_leaf() : false; | |
295 } | |
296 | |
297 // Return 'true' if this instruction matches an ideal 'If' node | |
298 bool InstructForm::is_ideal_if() const { | |
299 if( _matrule == NULL ) return false; | |
300 | |
301 return _matrule->is_ideal_if(); | |
302 } | |
303 | |
304 // Return 'true' if this instruction matches an ideal 'FastLock' node | |
305 bool InstructForm::is_ideal_fastlock() const { | |
306 if( _matrule == NULL ) return false; | |
307 | |
308 return _matrule->is_ideal_fastlock(); | |
309 } | |
310 | |
311 // Return 'true' if this instruction matches an ideal 'MemBarXXX' node | |
312 bool InstructForm::is_ideal_membar() const { | |
313 if( _matrule == NULL ) return false; | |
314 | |
315 return _matrule->is_ideal_membar(); | |
316 } | |
317 | |
318 // Return 'true' if this instruction matches an ideal 'LoadPC' node | |
319 bool InstructForm::is_ideal_loadPC() const { | |
320 if( _matrule == NULL ) return false; | |
321 | |
322 return _matrule->is_ideal_loadPC(); | |
323 } | |
324 | |
325 // Return 'true' if this instruction matches an ideal 'Box' node | |
326 bool InstructForm::is_ideal_box() const { | |
327 if( _matrule == NULL ) return false; | |
328 | |
329 return _matrule->is_ideal_box(); | |
330 } | |
331 | |
332 // Return 'true' if this instruction matches an ideal 'Goto' node | |
333 bool InstructForm::is_ideal_goto() const { | |
334 if( _matrule == NULL ) return false; | |
335 | |
336 return _matrule->is_ideal_goto(); | |
337 } | |
338 | |
339 // Return 'true' if this instruction matches an ideal 'Jump' node | |
340 bool InstructForm::is_ideal_jump() const { | |
341 if( _matrule == NULL ) return false; | |
342 | |
343 return _matrule->is_ideal_jump(); | |
344 } | |
345 | |
346 // Return 'true' if instruction matches ideal 'If' | 'Goto' | | |
347 // 'CountedLoopEnd' | 'Jump' | |
348 bool InstructForm::is_ideal_branch() const { | |
349 if( _matrule == NULL ) return false; | |
350 | |
351 return _matrule->is_ideal_if() || _matrule->is_ideal_goto() || _matrule->is_ideal_jump(); | |
352 } | |
353 | |
354 | |
355 // Return 'true' if this instruction matches an ideal 'Return' node | |
356 bool InstructForm::is_ideal_return() const { | |
357 if( _matrule == NULL ) return false; | |
358 | |
359 // Check MatchRule to see if the first entry is the ideal "Return" node | |
360 int index = 0; | |
361 if (_matrule->find_type("Return",index)) return true; | |
362 if (_matrule->find_type("Rethrow",index)) return true; | |
363 if (_matrule->find_type("TailCall",index)) return true; | |
364 if (_matrule->find_type("TailJump",index)) return true; | |
365 | |
366 return false; | |
367 } | |
368 | |
369 // Return 'true' if this instruction matches an ideal 'Halt' node | |
370 bool InstructForm::is_ideal_halt() const { | |
371 int index = 0; | |
372 return _matrule && _matrule->find_type("Halt",index); | |
373 } | |
374 | |
375 // Return 'true' if this instruction matches an ideal 'SafePoint' node | |
376 bool InstructForm::is_ideal_safepoint() const { | |
377 int index = 0; | |
378 return _matrule && _matrule->find_type("SafePoint",index); | |
379 } | |
380 | |
381 // Return 'true' if this instruction matches an ideal 'Nop' node | |
382 bool InstructForm::is_ideal_nop() const { | |
383 return _ident && _ident[0] == 'N' && _ident[1] == 'o' && _ident[2] == 'p' && _ident[3] == '_'; | |
384 } | |
385 | |
386 bool InstructForm::is_ideal_control() const { | |
387 if ( ! _matrule) return false; | |
388 | |
389 return is_ideal_return() || is_ideal_branch() || is_ideal_halt(); | |
390 } | |
391 | |
392 // Return 'true' if this instruction matches an ideal 'Call' node | |
393 Form::CallType InstructForm::is_ideal_call() const { | |
394 if( _matrule == NULL ) return Form::invalid_type; | |
395 | |
396 // Check MatchRule to see if the first entry is the ideal "Call" node | |
397 int idx = 0; | |
398 if(_matrule->find_type("CallStaticJava",idx)) return Form::JAVA_STATIC; | |
399 idx = 0; | |
400 if(_matrule->find_type("Lock",idx)) return Form::JAVA_STATIC; | |
401 idx = 0; | |
402 if(_matrule->find_type("Unlock",idx)) return Form::JAVA_STATIC; | |
403 idx = 0; | |
404 if(_matrule->find_type("CallDynamicJava",idx)) return Form::JAVA_DYNAMIC; | |
405 idx = 0; | |
406 if(_matrule->find_type("CallRuntime",idx)) return Form::JAVA_RUNTIME; | |
407 idx = 0; | |
408 if(_matrule->find_type("CallLeaf",idx)) return Form::JAVA_LEAF; | |
409 idx = 0; | |
410 if(_matrule->find_type("CallLeafNoFP",idx)) return Form::JAVA_LEAF; | |
411 idx = 0; | |
412 | |
413 return Form::invalid_type; | |
414 } | |
415 | |
416 // Return 'true' if this instruction matches an ideal 'Load?' node | |
417 Form::DataType InstructForm::is_ideal_load() const { | |
418 if( _matrule == NULL ) return Form::none; | |
419 | |
420 return _matrule->is_ideal_load(); | |
421 } | |
422 | |
855
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
423 // Return 'true' if this instruction matches an ideal 'LoadKlass' node |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
424 bool InstructForm::skip_antidep_check() const { |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
425 if( _matrule == NULL ) return false; |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
426 |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
427 return _matrule->skip_antidep_check(); |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
428 } |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
429 |
0 | 430 // Return 'true' if this instruction matches an ideal 'Load?' node |
431 Form::DataType InstructForm::is_ideal_store() const { | |
432 if( _matrule == NULL ) return Form::none; | |
433 | |
434 return _matrule->is_ideal_store(); | |
435 } | |
436 | |
437 // Return the input register that must match the output register | |
438 // If this is not required, return 0 | |
439 uint InstructForm::two_address(FormDict &globals) { | |
440 uint matching_input = 0; | |
441 if(_components.count() == 0) return 0; | |
442 | |
443 _components.reset(); | |
444 Component *comp = _components.iter(); | |
445 // Check if there is a DEF | |
446 if( comp->isa(Component::DEF) ) { | |
447 // Check that this is a register | |
448 const char *def_type = comp->_type; | |
449 const Form *form = globals[def_type]; | |
450 OperandForm *op = form->is_operand(); | |
451 if( op ) { | |
452 if( op->constrained_reg_class() != NULL && | |
453 op->interface_type(globals) == Form::register_interface ) { | |
454 // Remember the local name for equality test later | |
455 const char *def_name = comp->_name; | |
456 // Check if a component has the same name and is a USE | |
457 do { | |
458 if( comp->isa(Component::USE) && strcmp(comp->_name,def_name)==0 ) { | |
459 return operand_position_format(def_name); | |
460 } | |
461 } while( (comp = _components.iter()) != NULL); | |
462 } | |
463 } | |
464 } | |
465 | |
466 return 0; | |
467 } | |
468 | |
469 | |
470 // when chaining a constant to an instruction, returns 'true' and sets opType | |
471 Form::DataType InstructForm::is_chain_of_constant(FormDict &globals) { | |
472 const char *dummy = NULL; | |
473 const char *dummy2 = NULL; | |
474 return is_chain_of_constant(globals, dummy, dummy2); | |
475 } | |
476 Form::DataType InstructForm::is_chain_of_constant(FormDict &globals, | |
477 const char * &opTypeParam) { | |
478 const char *result = NULL; | |
479 | |
480 return is_chain_of_constant(globals, opTypeParam, result); | |
481 } | |
482 | |
483 Form::DataType InstructForm::is_chain_of_constant(FormDict &globals, | |
484 const char * &opTypeParam, const char * &resultParam) { | |
485 Form::DataType data_type = Form::none; | |
486 if ( ! _matrule) return data_type; | |
487 | |
488 // !!!!! | |
489 // The source of the chain rule is 'position = 1' | |
490 uint position = 1; | |
491 const char *result = NULL; | |
492 const char *name = NULL; | |
493 const char *opType = NULL; | |
494 // Here base_operand is looking for an ideal type to be returned (opType). | |
495 if ( _matrule->is_chain_rule(globals) | |
496 && _matrule->base_operand(position, globals, result, name, opType) ) { | |
497 data_type = ideal_to_const_type(opType); | |
498 | |
499 // if it isn't an ideal constant type, just return | |
500 if ( data_type == Form::none ) return data_type; | |
501 | |
502 // Ideal constant types also adjust the opType parameter. | |
503 resultParam = result; | |
504 opTypeParam = opType; | |
505 return data_type; | |
506 } | |
507 | |
508 return data_type; | |
509 } | |
510 | |
511 // Check if a simple chain rule | |
512 bool InstructForm::is_simple_chain_rule(FormDict &globals) const { | |
513 if( _matrule && _matrule->sets_result() | |
514 && _matrule->_rChild->_lChild == NULL | |
515 && globals[_matrule->_rChild->_opType] | |
516 && globals[_matrule->_rChild->_opType]->is_opclass() ) { | |
517 return true; | |
518 } | |
519 return false; | |
520 } | |
521 | |
522 // check for structural rematerialization | |
523 bool InstructForm::rematerialize(FormDict &globals, RegisterForm *registers ) { | |
524 bool rematerialize = false; | |
525 | |
526 Form::DataType data_type = is_chain_of_constant(globals); | |
527 if( data_type != Form::none ) | |
528 rematerialize = true; | |
529 | |
530 // Constants | |
531 if( _components.count() == 1 && _components[0]->is(Component::USE_DEF) ) | |
532 rematerialize = true; | |
533 | |
534 // Pseudo-constants (values easily available to the runtime) | |
535 if (is_empty_encoding() && is_tls_instruction()) | |
536 rematerialize = true; | |
537 | |
538 // 1-input, 1-output, such as copies or increments. | |
539 if( _components.count() == 2 && | |
540 _components[0]->is(Component::DEF) && | |
541 _components[1]->isa(Component::USE) ) | |
542 rematerialize = true; | |
543 | |
544 // Check for an ideal 'Load?' and eliminate rematerialize option | |
545 if ( is_ideal_load() != Form::none || // Ideal load? Do not rematerialize | |
546 is_ideal_copy() != Form::none || // Ideal copy? Do not rematerialize | |
547 is_expensive() != Form::none) { // Expensive? Do not rematerialize | |
548 rematerialize = false; | |
549 } | |
550 | |
551 // Always rematerialize the flags. They are more expensive to save & | |
552 // restore than to recompute (and possibly spill the compare's inputs). | |
553 if( _components.count() >= 1 ) { | |
554 Component *c = _components[0]; | |
555 const Form *form = globals[c->_type]; | |
556 OperandForm *opform = form->is_operand(); | |
557 if( opform ) { | |
558 // Avoid the special stack_slots register classes | |
559 const char *rc_name = opform->constrained_reg_class(); | |
560 if( rc_name ) { | |
561 if( strcmp(rc_name,"stack_slots") ) { | |
562 // Check for ideal_type of RegFlags | |
563 const char *type = opform->ideal_type( globals, registers ); | |
564 if( !strcmp(type,"RegFlags") ) | |
565 rematerialize = true; | |
566 } else | |
567 rematerialize = false; // Do not rematerialize things target stk | |
568 } | |
569 } | |
570 } | |
571 | |
572 return rematerialize; | |
573 } | |
574 | |
575 // loads from memory, so must check for anti-dependence | |
576 bool InstructForm::needs_anti_dependence_check(FormDict &globals) const { | |
855
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
577 if ( skip_antidep_check() ) return false; |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
578 |
0 | 579 // Machine independent loads must be checked for anti-dependences |
580 if( is_ideal_load() != Form::none ) return true; | |
581 | |
582 // !!!!! !!!!! !!!!! | |
583 // TEMPORARY | |
584 // if( is_simple_chain_rule(globals) ) return false; | |
585 | |
681 | 586 // String.(compareTo/equals/indexOf) and Arrays.equals use many memorys edges, |
587 // but writes none | |
0 | 588 if( _matrule && _matrule->_rChild && |
681 | 589 ( strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || |
590 strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || | |
591 strcmp(_matrule->_rChild->_opType,"StrIndexOf" )==0 || | |
592 strcmp(_matrule->_rChild->_opType,"AryEq" )==0 )) | |
0 | 593 return true; |
594 | |
595 // Check if instruction has a USE of a memory operand class, but no defs | |
596 bool USE_of_memory = false; | |
597 bool DEF_of_memory = false; | |
598 Component *comp = NULL; | |
599 ComponentList &components = (ComponentList &)_components; | |
600 | |
601 components.reset(); | |
602 while( (comp = components.iter()) != NULL ) { | |
603 const Form *form = globals[comp->_type]; | |
604 if( !form ) continue; | |
605 OpClassForm *op = form->is_opclass(); | |
606 if( !op ) continue; | |
607 if( form->interface_type(globals) == Form::memory_interface ) { | |
608 if( comp->isa(Component::USE) ) USE_of_memory = true; | |
609 if( comp->isa(Component::DEF) ) { | |
610 OperandForm *oper = form->is_operand(); | |
611 if( oper && oper->is_user_name_for_sReg() ) { | |
612 // Stack slots are unaliased memory handled by allocator | |
613 oper = oper; // debug stopping point !!!!! | |
614 } else { | |
615 DEF_of_memory = true; | |
616 } | |
617 } | |
618 } | |
619 } | |
620 return (USE_of_memory && !DEF_of_memory); | |
621 } | |
622 | |
623 | |
624 bool InstructForm::is_wide_memory_kill(FormDict &globals) const { | |
625 if( _matrule == NULL ) return false; | |
626 if( !_matrule->_opType ) return false; | |
627 | |
628 if( strcmp(_matrule->_opType,"MemBarRelease") == 0 ) return true; | |
629 if( strcmp(_matrule->_opType,"MemBarAcquire") == 0 ) return true; | |
630 | |
631 return false; | |
632 } | |
633 | |
634 int InstructForm::memory_operand(FormDict &globals) const { | |
635 // Machine independent loads must be checked for anti-dependences | |
636 // Check if instruction has a USE of a memory operand class, or a def. | |
637 int USE_of_memory = 0; | |
638 int DEF_of_memory = 0; | |
639 const char* last_memory_DEF = NULL; // to test DEF/USE pairing in asserts | |
640 Component *unique = NULL; | |
641 Component *comp = NULL; | |
642 ComponentList &components = (ComponentList &)_components; | |
643 | |
644 components.reset(); | |
645 while( (comp = components.iter()) != NULL ) { | |
646 const Form *form = globals[comp->_type]; | |
647 if( !form ) continue; | |
648 OpClassForm *op = form->is_opclass(); | |
649 if( !op ) continue; | |
650 if( op->stack_slots_only(globals) ) continue; | |
651 if( form->interface_type(globals) == Form::memory_interface ) { | |
652 if( comp->isa(Component::DEF) ) { | |
653 last_memory_DEF = comp->_name; | |
654 DEF_of_memory++; | |
655 unique = comp; | |
656 } else if( comp->isa(Component::USE) ) { | |
657 if( last_memory_DEF != NULL ) { | |
658 assert(0 == strcmp(last_memory_DEF, comp->_name), "every memory DEF is followed by a USE of the same name"); | |
659 last_memory_DEF = NULL; | |
660 } | |
661 USE_of_memory++; | |
662 if (DEF_of_memory == 0) // defs take precedence | |
663 unique = comp; | |
664 } else { | |
665 assert(last_memory_DEF == NULL, "unpaired memory DEF"); | |
666 } | |
667 } | |
668 } | |
669 assert(last_memory_DEF == NULL, "unpaired memory DEF"); | |
670 assert(USE_of_memory >= DEF_of_memory, "unpaired memory DEF"); | |
671 USE_of_memory -= DEF_of_memory; // treat paired DEF/USE as one occurrence | |
672 if( (USE_of_memory + DEF_of_memory) > 0 ) { | |
673 if( is_simple_chain_rule(globals) ) { | |
674 //fprintf(stderr, "Warning: chain rule is not really a memory user.\n"); | |
675 //((InstructForm*)this)->dump(); | |
676 // Preceding code prints nothing on sparc and these insns on intel: | |
677 // leaP8 leaP32 leaPIdxOff leaPIdxScale leaPIdxScaleOff leaP8 leaP32 | |
678 // leaPIdxOff leaPIdxScale leaPIdxScaleOff | |
679 return NO_MEMORY_OPERAND; | |
680 } | |
681 | |
682 if( DEF_of_memory == 1 ) { | |
683 assert(unique != NULL, ""); | |
684 if( USE_of_memory == 0 ) { | |
685 // unique def, no uses | |
686 } else { | |
687 // // unique def, some uses | |
688 // // must return bottom unless all uses match def | |
689 // unique = NULL; | |
690 } | |
691 } else if( DEF_of_memory > 0 ) { | |
692 // multiple defs, don't care about uses | |
693 unique = NULL; | |
694 } else if( USE_of_memory == 1) { | |
695 // unique use, no defs | |
696 assert(unique != NULL, ""); | |
697 } else if( USE_of_memory > 0 ) { | |
698 // multiple uses, no defs | |
699 unique = NULL; | |
700 } else { | |
701 assert(false, "bad case analysis"); | |
702 } | |
703 // process the unique DEF or USE, if there is one | |
704 if( unique == NULL ) { | |
705 return MANY_MEMORY_OPERANDS; | |
706 } else { | |
707 int pos = components.operand_position(unique->_name); | |
708 if( unique->isa(Component::DEF) ) { | |
709 pos += 1; // get corresponding USE from DEF | |
710 } | |
711 assert(pos >= 1, "I was just looking at it!"); | |
712 return pos; | |
713 } | |
714 } | |
715 | |
716 // missed the memory op?? | |
717 if( true ) { // %%% should not be necessary | |
718 if( is_ideal_store() != Form::none ) { | |
719 fprintf(stderr, "Warning: cannot find memory opnd in instr.\n"); | |
720 ((InstructForm*)this)->dump(); | |
721 // pretend it has multiple defs and uses | |
722 return MANY_MEMORY_OPERANDS; | |
723 } | |
724 if( is_ideal_load() != Form::none ) { | |
725 fprintf(stderr, "Warning: cannot find memory opnd in instr.\n"); | |
726 ((InstructForm*)this)->dump(); | |
727 // pretend it has multiple uses and no defs | |
728 return MANY_MEMORY_OPERANDS; | |
729 } | |
730 } | |
731 | |
732 return NO_MEMORY_OPERAND; | |
733 } | |
734 | |
735 | |
736 // This instruction captures the machine-independent bottom_type | |
737 // Expected use is for pointer vs oop determination for LoadP | |
1541
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1396
diff
changeset
|
738 bool InstructForm::captures_bottom_type(FormDict &globals) const { |
0 | 739 if( _matrule && _matrule->_rChild && |
740 (!strcmp(_matrule->_rChild->_opType,"CastPP") || // new result type | |
741 !strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
742 !strcmp(_matrule->_rChild->_opType,"DecodeN") || |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
743 !strcmp(_matrule->_rChild->_opType,"EncodeP") || |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
744 !strcmp(_matrule->_rChild->_opType,"LoadN") || |
216
8d191a7697e2
6715633: when matching a memory node the adr_type should not change
kvn
parents:
164
diff
changeset
|
745 !strcmp(_matrule->_rChild->_opType,"LoadNKlass") || |
0 | 746 !strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception |
747 !strcmp(_matrule->_rChild->_opType,"CheckCastPP")) ) return true; | |
748 else if ( is_ideal_load() == Form::idealP ) return true; | |
749 else if ( is_ideal_store() != Form::none ) return true; | |
750 | |
1541
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1396
diff
changeset
|
751 if (needs_base_oop_edge(globals)) return true; |
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1396
diff
changeset
|
752 |
0 | 753 return false; |
754 } | |
755 | |
756 | |
757 // Access instr_cost attribute or return NULL. | |
758 const char* InstructForm::cost() { | |
759 for (Attribute* cur = _attribs; cur != NULL; cur = (Attribute*)cur->_next) { | |
760 if( strcmp(cur->_ident,AttributeForm::_ins_cost) == 0 ) { | |
761 return cur->_val; | |
762 } | |
763 } | |
764 return NULL; | |
765 } | |
766 | |
767 // Return count of top-level operands. | |
768 uint InstructForm::num_opnds() { | |
769 int num_opnds = _components.num_operands(); | |
770 | |
771 // Need special handling for matching some ideal nodes | |
772 // i.e. Matching a return node | |
773 /* | |
774 if( _matrule ) { | |
775 if( strcmp(_matrule->_opType,"Return" )==0 || | |
776 strcmp(_matrule->_opType,"Halt" )==0 ) | |
777 return 3; | |
778 } | |
779 */ | |
780 return num_opnds; | |
781 } | |
782 | |
783 // Return count of unmatched operands. | |
784 uint InstructForm::num_post_match_opnds() { | |
785 uint num_post_match_opnds = _components.count(); | |
786 uint num_match_opnds = _components.match_count(); | |
787 num_post_match_opnds = num_post_match_opnds - num_match_opnds; | |
788 | |
789 return num_post_match_opnds; | |
790 } | |
791 | |
792 // Return the number of leaves below this complex operand | |
793 uint InstructForm::num_consts(FormDict &globals) const { | |
794 if ( ! _matrule) return 0; | |
795 | |
796 // This is a recursive invocation on all operands in the matchrule | |
797 return _matrule->num_consts(globals); | |
798 } | |
799 | |
800 // Constants in match rule with specified type | |
801 uint InstructForm::num_consts(FormDict &globals, Form::DataType type) const { | |
802 if ( ! _matrule) return 0; | |
803 | |
804 // This is a recursive invocation on all operands in the matchrule | |
805 return _matrule->num_consts(globals, type); | |
806 } | |
807 | |
808 | |
809 // Return the register class associated with 'leaf'. | |
810 const char *InstructForm::out_reg_class(FormDict &globals) { | |
811 assert( false, "InstructForm::out_reg_class(FormDict &globals); Not Implemented"); | |
812 | |
813 return NULL; | |
814 } | |
815 | |
816 | |
817 | |
818 // Lookup the starting position of inputs we are interested in wrt. ideal nodes | |
819 uint InstructForm::oper_input_base(FormDict &globals) { | |
820 if( !_matrule ) return 1; // Skip control for most nodes | |
821 | |
822 // Need special handling for matching some ideal nodes | |
823 // i.e. Matching a return node | |
824 if( strcmp(_matrule->_opType,"Return" )==0 || | |
825 strcmp(_matrule->_opType,"Rethrow" )==0 || | |
826 strcmp(_matrule->_opType,"TailCall" )==0 || | |
827 strcmp(_matrule->_opType,"TailJump" )==0 || | |
828 strcmp(_matrule->_opType,"SafePoint" )==0 || | |
829 strcmp(_matrule->_opType,"Halt" )==0 ) | |
830 return AdlcVMDeps::Parms; // Skip the machine-state edges | |
831 | |
832 if( _matrule->_rChild && | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
855
diff
changeset
|
833 ( strcmp(_matrule->_rChild->_opType,"AryEq" )==0 || |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
855
diff
changeset
|
834 strcmp(_matrule->_rChild->_opType,"StrComp" )==0 || |
681 | 835 strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 || |
836 strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 )) { | |
986
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
855
diff
changeset
|
837 // String.(compareTo/equals/indexOf) and Arrays.equals |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
855
diff
changeset
|
838 // take 1 control and 1 memory edges. |
62001a362ce9
6827605: new String intrinsics may prevent EA scalar replacement
kvn
parents:
855
diff
changeset
|
839 return 2; |
0 | 840 } |
841 | |
842 // Check for handling of 'Memory' input/edge in the ideal world. | |
843 // The AD file writer is shielded from knowledge of these edges. | |
844 int base = 1; // Skip control | |
845 base += _matrule->needs_ideal_memory_edge(globals); | |
846 | |
847 // Also skip the base-oop value for uses of derived oops. | |
848 // The AD file writer is shielded from knowledge of these edges. | |
849 base += needs_base_oop_edge(globals); | |
850 | |
851 return base; | |
852 } | |
853 | |
854 // Implementation does not modify state of internal structures | |
855 void InstructForm::build_components() { | |
856 // Add top-level operands to the components | |
857 if (_matrule) _matrule->append_components(_localNames, _components); | |
858 | |
859 // Add parameters that "do not appear in match rule". | |
860 bool has_temp = false; | |
861 const char *name; | |
862 const char *kill_name = NULL; | |
863 for (_parameters.reset(); (name = _parameters.iter()) != NULL;) { | |
864 OperandForm *opForm = (OperandForm*)_localNames[name]; | |
865 | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
866 Effect* e = NULL; |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
867 { |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
868 const Form* form = _effects[name]; |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
869 e = form ? form->is_effect() : NULL; |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
870 } |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
871 |
0 | 872 if (e != NULL) { |
873 has_temp |= e->is(Component::TEMP); | |
874 | |
875 // KILLs must be declared after any TEMPs because TEMPs are real | |
876 // uses so their operand numbering must directly follow the real | |
877 // inputs from the match rule. Fixing the numbering seems | |
878 // complex so simply enforce the restriction during parse. | |
879 if (kill_name != NULL && | |
880 e->isa(Component::TEMP) && !e->isa(Component::DEF)) { | |
881 OperandForm* kill = (OperandForm*)_localNames[kill_name]; | |
882 globalAD->syntax_err(_linenum, "%s: %s %s must be at the end of the argument list\n", | |
883 _ident, kill->_ident, kill_name); | |
602
ed6404fac86b
6810855: KILL vs. TEMP ordering restrictions are too strong
never
parents:
599
diff
changeset
|
884 } else if (e->isa(Component::KILL) && !e->isa(Component::USE)) { |
0 | 885 kill_name = name; |
886 } | |
887 } | |
888 | |
889 const Component *component = _components.search(name); | |
890 if ( component == NULL ) { | |
891 if (e) { | |
892 _components.insert(name, opForm->_ident, e->_use_def, false); | |
893 component = _components.search(name); | |
894 if (component->isa(Component::USE) && !component->isa(Component::TEMP) && _matrule) { | |
895 const Form *form = globalAD->globalNames()[component->_type]; | |
896 assert( form, "component type must be a defined form"); | |
897 OperandForm *op = form->is_operand(); | |
898 if (op->_interface && op->_interface->is_RegInterface()) { | |
899 globalAD->syntax_err(_linenum, "%s: illegal USE of non-input: %s %s\n", | |
900 _ident, opForm->_ident, name); | |
901 } | |
902 } | |
903 } else { | |
904 // This would be a nice warning but it triggers in a few places in a benign way | |
905 // if (_matrule != NULL && !expands()) { | |
906 // globalAD->syntax_err(_linenum, "%s: %s %s not mentioned in effect or match rule\n", | |
907 // _ident, opForm->_ident, name); | |
908 // } | |
909 _components.insert(name, opForm->_ident, Component::INVALID, false); | |
910 } | |
911 } | |
912 else if (e) { | |
913 // Component was found in the list | |
914 // Check if there is a new effect that requires an extra component. | |
915 // This happens when adding 'USE' to a component that is not yet one. | |
916 if ((!component->isa( Component::USE) && ((e->_use_def & Component::USE) != 0))) { | |
917 if (component->isa(Component::USE) && _matrule) { | |
918 const Form *form = globalAD->globalNames()[component->_type]; | |
919 assert( form, "component type must be a defined form"); | |
920 OperandForm *op = form->is_operand(); | |
921 if (op->_interface && op->_interface->is_RegInterface()) { | |
922 globalAD->syntax_err(_linenum, "%s: illegal USE of non-input: %s %s\n", | |
923 _ident, opForm->_ident, name); | |
924 } | |
925 } | |
926 _components.insert(name, opForm->_ident, e->_use_def, false); | |
927 } else { | |
928 Component *comp = (Component*)component; | |
929 comp->promote_use_def_info(e->_use_def); | |
930 } | |
931 // Component positions are zero based. | |
932 int pos = _components.operand_position(name); | |
933 assert( ! (component->isa(Component::DEF) && (pos >= 1)), | |
934 "Component::DEF can only occur in the first position"); | |
935 } | |
936 } | |
937 | |
938 // Resolving the interactions between expand rules and TEMPs would | |
939 // be complex so simply disallow it. | |
940 if (_matrule == NULL && has_temp) { | |
941 globalAD->syntax_err(_linenum, "%s: TEMPs without match rule isn't supported\n", _ident); | |
942 } | |
943 | |
944 return; | |
945 } | |
946 | |
947 // Return zero-based position in component list; -1 if not in list. | |
948 int InstructForm::operand_position(const char *name, int usedef) { | |
949 return unique_opnds_idx(_components.operand_position(name, usedef)); | |
950 } | |
951 | |
952 int InstructForm::operand_position_format(const char *name) { | |
953 return unique_opnds_idx(_components.operand_position_format(name)); | |
954 } | |
955 | |
956 // Return zero-based position in component list; -1 if not in list. | |
957 int InstructForm::label_position() { | |
958 return unique_opnds_idx(_components.label_position()); | |
959 } | |
960 | |
961 int InstructForm::method_position() { | |
962 return unique_opnds_idx(_components.method_position()); | |
963 } | |
964 | |
965 // Return number of relocation entries needed for this instruction. | |
966 uint InstructForm::reloc(FormDict &globals) { | |
967 uint reloc_entries = 0; | |
968 // Check for "Call" nodes | |
969 if ( is_ideal_call() ) ++reloc_entries; | |
970 if ( is_ideal_return() ) ++reloc_entries; | |
971 if ( is_ideal_safepoint() ) ++reloc_entries; | |
972 | |
973 | |
974 // Check if operands MAYBE oop pointers, by checking for ConP elements | |
975 // Proceed through the leaves of the match-tree and check for ConPs | |
976 if ( _matrule != NULL ) { | |
977 uint position = 0; | |
978 const char *result = NULL; | |
979 const char *name = NULL; | |
980 const char *opType = NULL; | |
981 while (_matrule->base_operand(position, globals, result, name, opType)) { | |
982 if ( strcmp(opType,"ConP") == 0 ) { | |
983 #ifdef SPARC | |
984 reloc_entries += 2; // 1 for sethi + 1 for setlo | |
985 #else | |
986 ++reloc_entries; | |
987 #endif | |
988 } | |
989 ++position; | |
990 } | |
991 } | |
992 | |
993 // Above is only a conservative estimate | |
994 // because it did not check contents of operand classes. | |
995 // !!!!! !!!!! | |
996 // Add 1 to reloc info for each operand class in the component list. | |
997 Component *comp; | |
998 _components.reset(); | |
999 while ( (comp = _components.iter()) != NULL ) { | |
1000 const Form *form = globals[comp->_type]; | |
1001 assert( form, "Did not find component's type in global names"); | |
1002 const OpClassForm *opc = form->is_opclass(); | |
1003 const OperandForm *oper = form->is_operand(); | |
1004 if ( opc && (oper == NULL) ) { | |
1005 ++reloc_entries; | |
1006 } else if ( oper ) { | |
1007 // floats and doubles loaded out of method's constant pool require reloc info | |
1008 Form::DataType type = oper->is_base_constant(globals); | |
1009 if ( (type == Form::idealF) || (type == Form::idealD) ) { | |
1010 ++reloc_entries; | |
1011 } | |
1012 } | |
1013 } | |
1014 | |
1015 // Float and Double constants may come from the CodeBuffer table | |
1016 // and require relocatable addresses for access | |
1017 // !!!!! | |
1018 // Check for any component being an immediate float or double. | |
1019 Form::DataType data_type = is_chain_of_constant(globals); | |
1020 if( data_type==idealD || data_type==idealF ) { | |
1021 #ifdef SPARC | |
1022 // sparc required more relocation entries for floating constants | |
1023 // (expires 9/98) | |
1024 reloc_entries += 6; | |
1025 #else | |
1026 reloc_entries++; | |
1027 #endif | |
1028 } | |
1029 | |
1030 return reloc_entries; | |
1031 } | |
1032 | |
1033 // Utility function defined in archDesc.cpp | |
1034 extern bool is_def(int usedef); | |
1035 | |
1036 // Return the result of reducing an instruction | |
1037 const char *InstructForm::reduce_result() { | |
1038 const char* result = "Universe"; // default | |
1039 _components.reset(); | |
1040 Component *comp = _components.iter(); | |
1041 if (comp != NULL && comp->isa(Component::DEF)) { | |
1042 result = comp->_type; | |
1043 // Override this if the rule is a store operation: | |
1044 if (_matrule && _matrule->_rChild && | |
1045 is_store_to_memory(_matrule->_rChild->_opType)) | |
1046 result = "Universe"; | |
1047 } | |
1048 return result; | |
1049 } | |
1050 | |
1051 // Return the name of the operand on the right hand side of the binary match | |
1052 // Return NULL if there is no right hand side | |
1053 const char *InstructForm::reduce_right(FormDict &globals) const { | |
1054 if( _matrule == NULL ) return NULL; | |
1055 return _matrule->reduce_right(globals); | |
1056 } | |
1057 | |
1058 // Similar for left | |
1059 const char *InstructForm::reduce_left(FormDict &globals) const { | |
1060 if( _matrule == NULL ) return NULL; | |
1061 return _matrule->reduce_left(globals); | |
1062 } | |
1063 | |
1064 | |
1065 // Base class for this instruction, MachNode except for calls | |
1541
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1396
diff
changeset
|
1066 const char *InstructForm::mach_base_class(FormDict &globals) const { |
0 | 1067 if( is_ideal_call() == Form::JAVA_STATIC ) { |
1068 return "MachCallStaticJavaNode"; | |
1069 } | |
1070 else if( is_ideal_call() == Form::JAVA_DYNAMIC ) { | |
1071 return "MachCallDynamicJavaNode"; | |
1072 } | |
1073 else if( is_ideal_call() == Form::JAVA_RUNTIME ) { | |
1074 return "MachCallRuntimeNode"; | |
1075 } | |
1076 else if( is_ideal_call() == Form::JAVA_LEAF ) { | |
1077 return "MachCallLeafNode"; | |
1078 } | |
1079 else if (is_ideal_return()) { | |
1080 return "MachReturnNode"; | |
1081 } | |
1082 else if (is_ideal_halt()) { | |
1083 return "MachHaltNode"; | |
1084 } | |
1085 else if (is_ideal_safepoint()) { | |
1086 return "MachSafePointNode"; | |
1087 } | |
1088 else if (is_ideal_if()) { | |
1089 return "MachIfNode"; | |
1090 } | |
1091 else if (is_ideal_fastlock()) { | |
1092 return "MachFastLockNode"; | |
1093 } | |
1094 else if (is_ideal_nop()) { | |
1095 return "MachNopNode"; | |
1096 } | |
1541
b5fdf39b9749
6953576: bottom_type for matched AddPNodes doesn't always agree with ideal
never
parents:
1396
diff
changeset
|
1097 else if (captures_bottom_type(globals)) { |
0 | 1098 return "MachTypeNode"; |
1099 } else { | |
1100 return "MachNode"; | |
1101 } | |
1102 assert( false, "ShouldNotReachHere()"); | |
1103 return NULL; | |
1104 } | |
1105 | |
1106 // Compare the instruction predicates for textual equality | |
1107 bool equivalent_predicates( const InstructForm *instr1, const InstructForm *instr2 ) { | |
1108 const Predicate *pred1 = instr1->_predicate; | |
1109 const Predicate *pred2 = instr2->_predicate; | |
1110 if( pred1 == NULL && pred2 == NULL ) { | |
1111 // no predicates means they are identical | |
1112 return true; | |
1113 } | |
1114 if( pred1 != NULL && pred2 != NULL ) { | |
1115 // compare the predicates | |
475
284d0af00d53
6771309: debugging AD files is difficult without #line directives in generated code
jrose
parents:
420
diff
changeset
|
1116 if (ADLParser::equivalent_expressions(pred1->_pred, pred2->_pred)) { |
0 | 1117 return true; |
1118 } | |
1119 } | |
1120 | |
1121 return false; | |
1122 } | |
1123 | |
1124 // Check if this instruction can cisc-spill to 'alternate' | |
1125 bool InstructForm::cisc_spills_to(ArchDesc &AD, InstructForm *instr) { | |
1126 assert( _matrule != NULL && instr->_matrule != NULL, "must have match rules"); | |
1127 // Do not replace if a cisc-version has been found. | |
1128 if( cisc_spill_operand() != Not_cisc_spillable ) return false; | |
1129 | |
1130 int cisc_spill_operand = Maybe_cisc_spillable; | |
1131 char *result = NULL; | |
1132 char *result2 = NULL; | |
1133 const char *op_name = NULL; | |
1134 const char *reg_type = NULL; | |
1135 FormDict &globals = AD.globalNames(); | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
1136 cisc_spill_operand = _matrule->matchrule_cisc_spill_match(globals, AD.get_registers(), instr->_matrule, op_name, reg_type); |
0 | 1137 if( (cisc_spill_operand != Not_cisc_spillable) && (op_name != NULL) && equivalent_predicates(this, instr) ) { |
1138 cisc_spill_operand = operand_position(op_name, Component::USE); | |
1139 int def_oper = operand_position(op_name, Component::DEF); | |
1140 if( def_oper == NameList::Not_in_list && instr->num_opnds() == num_opnds()) { | |
1141 // Do not support cisc-spilling for destination operands and | |
1142 // make sure they have the same number of operands. | |
1143 _cisc_spill_alternate = instr; | |
1144 instr->set_cisc_alternate(true); | |
1145 if( AD._cisc_spill_debug ) { | |
1146 fprintf(stderr, "Instruction %s cisc-spills-to %s\n", _ident, instr->_ident); | |
1147 fprintf(stderr, " using operand %s %s at index %d\n", reg_type, op_name, cisc_spill_operand); | |
1148 } | |
1149 // Record that a stack-version of the reg_mask is needed | |
1150 // !!!!! | |
1151 OperandForm *oper = (OperandForm*)(globals[reg_type]->is_operand()); | |
1152 assert( oper != NULL, "cisc-spilling non operand"); | |
1153 const char *reg_class_name = oper->constrained_reg_class(); | |
1154 AD.set_stack_or_reg(reg_class_name); | |
1155 const char *reg_mask_name = AD.reg_mask(*oper); | |
1156 set_cisc_reg_mask_name(reg_mask_name); | |
1157 const char *stack_or_reg_mask_name = AD.stack_or_reg_mask(*oper); | |
1158 } else { | |
1159 cisc_spill_operand = Not_cisc_spillable; | |
1160 } | |
1161 } else { | |
1162 cisc_spill_operand = Not_cisc_spillable; | |
1163 } | |
1164 | |
1165 set_cisc_spill_operand(cisc_spill_operand); | |
1166 return (cisc_spill_operand != Not_cisc_spillable); | |
1167 } | |
1168 | |
1169 // Check to see if this instruction can be replaced with the short branch | |
1170 // instruction `short-branch' | |
1171 bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch) { | |
1172 if (_matrule != NULL && | |
1173 this != short_branch && // Don't match myself | |
1174 !is_short_branch() && // Don't match another short branch variant | |
1175 reduce_result() != NULL && | |
1176 strcmp(reduce_result(), short_branch->reduce_result()) == 0 && | |
1177 _matrule->equivalent(AD.globalNames(), short_branch->_matrule)) { | |
1178 // The instructions are equivalent. | |
1179 if (AD._short_branch_debug) { | |
1180 fprintf(stderr, "Instruction %s has short form %s\n", _ident, short_branch->_ident); | |
1181 } | |
1182 _short_branch_form = short_branch; | |
1183 return true; | |
1184 } | |
1185 return false; | |
1186 } | |
1187 | |
1188 | |
1189 // --------------------------- FILE *output_routines | |
1190 // | |
1191 // Generate the format call for the replacement variable | |
1192 void InstructForm::rep_var_format(FILE *fp, const char *rep_var) { | |
1193 // Find replacement variable's type | |
1194 const Form *form = _localNames[rep_var]; | |
1195 if (form == NULL) { | |
1196 fprintf(stderr, "unknown replacement variable in format statement: '%s'\n", rep_var); | |
1197 assert(false, "ShouldNotReachHere()"); | |
1198 } | |
1199 OpClassForm *opc = form->is_opclass(); | |
1200 assert( opc, "replacement variable was not found in local names"); | |
1201 // Lookup the index position of the replacement variable | |
1202 int idx = operand_position_format(rep_var); | |
1203 if ( idx == -1 ) { | |
1204 assert( strcmp(opc->_ident,"label")==0, "Unimplemented"); | |
1205 assert( false, "ShouldNotReachHere()"); | |
1206 } | |
1207 | |
1208 if (is_noninput_operand(idx)) { | |
1209 // This component isn't in the input array. Print out the static | |
1210 // name of the register. | |
1211 OperandForm* oper = form->is_operand(); | |
1212 if (oper != NULL && oper->is_bound_register()) { | |
1213 const RegDef* first = oper->get_RegClass()->find_first_elem(); | |
1214 fprintf(fp, " tty->print(\"%s\");\n", first->_regname); | |
1215 } else { | |
1216 globalAD->syntax_err(_linenum, "In %s can't find format for %s %s", _ident, opc->_ident, rep_var); | |
1217 } | |
1218 } else { | |
1219 // Output the format call for this operand | |
1220 fprintf(fp,"opnd_array(%d)->",idx); | |
1221 if (idx == 0) | |
1222 fprintf(fp,"int_format(ra, this, st); // %s\n", rep_var); | |
1223 else | |
1224 fprintf(fp,"ext_format(ra, this,idx%d, st); // %s\n", idx, rep_var ); | |
1225 } | |
1226 } | |
1227 | |
1228 // Seach through operands to determine parameters unique positions. | |
1229 void InstructForm::set_unique_opnds() { | |
1230 uint* uniq_idx = NULL; | |
599
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1231 int nopnds = num_opnds(); |
0 | 1232 uint num_uniq = nopnds; |
599
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1233 int i; |
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1234 _uniq_idx_length = 0; |
0 | 1235 if ( nopnds > 0 ) { |
599
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1236 // Allocate index array. Worst case we're mapping from each |
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1237 // component back to an index and any DEF always goes at 0 so the |
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1238 // length of the array has to be the number of components + 1. |
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1239 _uniq_idx_length = _components.count() + 1; |
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1240 uniq_idx = (uint*) malloc(sizeof(uint)*(_uniq_idx_length)); |
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1241 for( i = 0; i < _uniq_idx_length; i++ ) { |
0 | 1242 uniq_idx[i] = i; |
1243 } | |
1244 } | |
1245 // Do it only if there is a match rule and no expand rule. With an | |
1246 // expand rule it is done by creating new mach node in Expand() | |
1247 // method. | |
1248 if ( nopnds > 0 && _matrule != NULL && _exprule == NULL ) { | |
1249 const char *name; | |
1250 uint count; | |
1251 bool has_dupl_use = false; | |
1252 | |
1253 _parameters.reset(); | |
1254 while( (name = _parameters.iter()) != NULL ) { | |
1255 count = 0; | |
599
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1256 int position = 0; |
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1257 int uniq_position = 0; |
0 | 1258 _components.reset(); |
1259 Component *comp = NULL; | |
1260 if( sets_result() ) { | |
1261 comp = _components.iter(); | |
1262 position++; | |
1263 } | |
1264 // The next code is copied from the method operand_position(). | |
1265 for (; (comp = _components.iter()) != NULL; ++position) { | |
1266 // When the first component is not a DEF, | |
1267 // leave space for the result operand! | |
1268 if ( position==0 && (! comp->isa(Component::DEF)) ) { | |
1269 ++position; | |
1270 } | |
1271 if( strcmp(name, comp->_name)==0 ) { | |
1272 if( ++count > 1 ) { | |
599
0ad1cb407fa1
6805427: adlc compiler may generate incorrect machnode emission code
never
parents:
558
diff
changeset
|
1273 assert(position < _uniq_idx_length, "out of bounds"); |
0 | 1274 uniq_idx[position] = uniq_position; |
1275 has_dupl_use = true; | |
1276 } else { | |
1277 uniq_position = position; | |
1278 } | |
1279 } | |
1280 if( comp->isa(Component::DEF) | |
1281 && comp->isa(Component::USE) ) { | |
1282 ++position; | |
1283 if( position != 1 ) | |
1284 --position; // only use two slots for the 1st USE_DEF | |
1285 } | |
1286 } | |
1287 } | |
1288 if( has_dupl_use ) { | |
1289 for( i = 1; i < nopnds; i++ ) | |
1290 if( i != uniq_idx[i] ) | |
1291 break; | |
1292 int j = i; | |
1293 for( ; i < nopnds; i++ ) | |
1294 if( i == uniq_idx[i] ) | |
1295 uniq_idx[i] = j++; | |
1296 num_uniq = j; | |
1297 } | |
1298 } | |
1299 _uniq_idx = uniq_idx; | |
1300 _num_uniq = num_uniq; | |
1301 } | |
1302 | |
605 | 1303 // Generate index values needed for determining the operand position |
0 | 1304 void InstructForm::index_temps(FILE *fp, FormDict &globals, const char *prefix, const char *receiver) { |
1305 uint idx = 0; // position of operand in match rule | |
1306 int cur_num_opnds = num_opnds(); | |
1307 | |
1308 // Compute the index into vector of operand pointers: | |
1309 // idx0=0 is used to indicate that info comes from this same node, not from input edge. | |
1310 // idx1 starts at oper_input_base() | |
1311 if ( cur_num_opnds >= 1 ) { | |
1312 fprintf(fp," // Start at oper_input_base() and count operands\n"); | |
1313 fprintf(fp," unsigned %sidx0 = %d;\n", prefix, oper_input_base(globals)); | |
1314 fprintf(fp," unsigned %sidx1 = %d;\n", prefix, oper_input_base(globals)); | |
1315 | |
1316 // Generate starting points for other unique operands if they exist | |
1317 for ( idx = 2; idx < num_unique_opnds(); ++idx ) { | |
1318 if( *receiver == 0 ) { | |
1319 fprintf(fp," unsigned %sidx%d = %sidx%d + opnd_array(%d)->num_edges();\n", | |
1320 prefix, idx, prefix, idx-1, idx-1 ); | |
1321 } else { | |
1322 fprintf(fp," unsigned %sidx%d = %sidx%d + %s_opnds[%d]->num_edges();\n", | |
1323 prefix, idx, prefix, idx-1, receiver, idx-1 ); | |
1324 } | |
1325 } | |
1326 } | |
1327 if( *receiver != 0 ) { | |
1328 // This value is used by generate_peepreplace when copying a node. | |
1329 // Don't emit it in other cases since it can hide bugs with the | |
1330 // use invalid idx's. | |
1331 fprintf(fp," unsigned %sidx%d = %sreq(); \n", prefix, idx, receiver); | |
1332 } | |
1333 | |
1334 } | |
1335 | |
1336 // --------------------------- | |
1337 bool InstructForm::verify() { | |
1338 // !!!!! !!!!! | |
1339 // Check that a "label" operand occurs last in the operand list, if present | |
1340 return true; | |
1341 } | |
1342 | |
1343 void InstructForm::dump() { | |
1344 output(stderr); | |
1345 } | |
1346 | |
1347 void InstructForm::output(FILE *fp) { | |
1348 fprintf(fp,"\nInstruction: %s\n", (_ident?_ident:"")); | |
1349 if (_matrule) _matrule->output(fp); | |
1350 if (_insencode) _insencode->output(fp); | |
1351 if (_opcode) _opcode->output(fp); | |
1352 if (_attribs) _attribs->output(fp); | |
1353 if (_predicate) _predicate->output(fp); | |
1354 if (_effects.Size()) { | |
1355 fprintf(fp,"Effects\n"); | |
1356 _effects.dump(); | |
1357 } | |
1358 if (_exprule) _exprule->output(fp); | |
1359 if (_rewrule) _rewrule->output(fp); | |
1360 if (_format) _format->output(fp); | |
1361 if (_peephole) _peephole->output(fp); | |
1362 } | |
1363 | |
1364 void MachNodeForm::dump() { | |
1365 output(stderr); | |
1366 } | |
1367 | |
1368 void MachNodeForm::output(FILE *fp) { | |
1369 fprintf(fp,"\nMachNode: %s\n", (_ident?_ident:"")); | |
1370 } | |
1371 | |
1372 //------------------------------build_predicate-------------------------------- | |
1373 // Build instruction predicates. If the user uses the same operand name | |
1374 // twice, we need to check that the operands are pointer-eequivalent in | |
1375 // the DFA during the labeling process. | |
1376 Predicate *InstructForm::build_predicate() { | |
1377 char buf[1024], *s=buf; | |
1378 Dict names(cmpstr,hashstr,Form::arena); // Map Names to counts | |
1379 | |
1380 MatchNode *mnode = | |
1381 strcmp(_matrule->_opType, "Set") ? _matrule : _matrule->_rChild; | |
1382 mnode->count_instr_names(names); | |
1383 | |
1384 uint first = 1; | |
1385 // Start with the predicate supplied in the .ad file. | |
1386 if( _predicate ) { | |
1387 if( first ) first=0; | |
1388 strcpy(s,"("); s += strlen(s); | |
1389 strcpy(s,_predicate->_pred); | |
1390 s += strlen(s); | |
1391 strcpy(s,")"); s += strlen(s); | |
1392 } | |
1393 for( DictI i(&names); i.test(); ++i ) { | |
1394 uintptr_t cnt = (uintptr_t)i._value; | |
1395 if( cnt > 1 ) { // Need a predicate at all? | |
1396 assert( cnt == 2, "Unimplemented" ); | |
1397 // Handle many pairs | |
1398 if( first ) first=0; | |
1399 else { // All tests must pass, so use '&&' | |
1400 strcpy(s," && "); | |
1401 s += strlen(s); | |
1402 } | |
1403 // Add predicate to working buffer | |
1404 sprintf(s,"/*%s*/(",(char*)i._key); | |
1405 s += strlen(s); | |
1406 mnode->build_instr_pred(s,(char*)i._key,0); | |
1407 s += strlen(s); | |
1408 strcpy(s," == "); s += strlen(s); | |
1409 mnode->build_instr_pred(s,(char*)i._key,1); | |
1410 s += strlen(s); | |
1411 strcpy(s,")"); s += strlen(s); | |
1412 } | |
1413 } | |
1414 if( s == buf ) s = NULL; | |
1415 else { | |
1416 assert( strlen(buf) < sizeof(buf), "String buffer overflow" ); | |
1417 s = strdup(buf); | |
1418 } | |
1419 return new Predicate(s); | |
1420 } | |
1421 | |
1422 //------------------------------EncodeForm------------------------------------- | |
1423 // Constructor | |
1424 EncodeForm::EncodeForm() | |
1425 : _encClass(cmpstr,hashstr, Form::arena) { | |
1426 } | |
1427 EncodeForm::~EncodeForm() { | |
1428 } | |
1429 | |
1430 // record a new register class | |
1431 EncClass *EncodeForm::add_EncClass(const char *className) { | |
1432 EncClass *encClass = new EncClass(className); | |
1433 _eclasses.addName(className); | |
1434 _encClass.Insert(className,encClass); | |
1435 return encClass; | |
1436 } | |
1437 | |
1438 // Lookup the function body for an encoding class | |
1439 EncClass *EncodeForm::encClass(const char *className) { | |
1440 assert( className != NULL, "Must provide a defined encoding name"); | |
1441 | |
1442 EncClass *encClass = (EncClass*)_encClass[className]; | |
1443 return encClass; | |
1444 } | |
1445 | |
1446 // Lookup the function body for an encoding class | |
1447 const char *EncodeForm::encClassBody(const char *className) { | |
1448 if( className == NULL ) return NULL; | |
1449 | |
1450 EncClass *encClass = (EncClass*)_encClass[className]; | |
1451 assert( encClass != NULL, "Encode Class is missing."); | |
1452 encClass->_code.reset(); | |
1453 const char *code = (const char*)encClass->_code.iter(); | |
1454 assert( code != NULL, "Found an empty encode class body."); | |
1455 | |
1456 return code; | |
1457 } | |
1458 | |
1459 // Lookup the function body for an encoding class | |
1460 const char *EncodeForm::encClassPrototype(const char *className) { | |
1461 assert( className != NULL, "Encode class name must be non NULL."); | |
1462 | |
1463 return className; | |
1464 } | |
1465 | |
1466 void EncodeForm::dump() { // Debug printer | |
1467 output(stderr); | |
1468 } | |
1469 | |
1470 void EncodeForm::output(FILE *fp) { // Write info to output files | |
1471 const char *name; | |
1472 fprintf(fp,"\n"); | |
1473 fprintf(fp,"-------------------- Dump EncodeForm --------------------\n"); | |
1474 for (_eclasses.reset(); (name = _eclasses.iter()) != NULL;) { | |
1475 ((EncClass*)_encClass[name])->output(fp); | |
1476 } | |
1477 fprintf(fp,"-------------------- end EncodeForm --------------------\n"); | |
1478 } | |
1479 //------------------------------EncClass--------------------------------------- | |
1480 EncClass::EncClass(const char *name) | |
1481 : _localNames(cmpstr,hashstr, Form::arena), _name(name) { | |
1482 } | |
1483 EncClass::~EncClass() { | |
1484 } | |
1485 | |
1486 // Add a parameter <type,name> pair | |
1487 void EncClass::add_parameter(const char *parameter_type, const char *parameter_name) { | |
1488 _parameter_type.addName( parameter_type ); | |
1489 _parameter_name.addName( parameter_name ); | |
1490 } | |
1491 | |
1492 // Verify operand types in parameter list | |
1493 bool EncClass::check_parameter_types(FormDict &globals) { | |
1494 // !!!!! | |
1495 return false; | |
1496 } | |
1497 | |
1498 // Add the decomposed "code" sections of an encoding's code-block | |
1499 void EncClass::add_code(const char *code) { | |
1500 _code.addName(code); | |
1501 } | |
1502 | |
1503 // Add the decomposed "replacement variables" of an encoding's code-block | |
1504 void EncClass::add_rep_var(char *replacement_var) { | |
1505 _code.addName(NameList::_signal); | |
1506 _rep_vars.addName(replacement_var); | |
1507 } | |
1508 | |
1509 // Lookup the function body for an encoding class | |
1510 int EncClass::rep_var_index(const char *rep_var) { | |
1511 uint position = 0; | |
1512 const char *name = NULL; | |
1513 | |
1514 _parameter_name.reset(); | |
1515 while ( (name = _parameter_name.iter()) != NULL ) { | |
1516 if ( strcmp(rep_var,name) == 0 ) return position; | |
1517 ++position; | |
1518 } | |
1519 | |
1520 return -1; | |
1521 } | |
1522 | |
1523 // Check after parsing | |
1524 bool EncClass::verify() { | |
1525 // 1!!!! | |
1526 // Check that each replacement variable, '$name' in architecture description | |
1527 // is actually a local variable for this encode class, or a reserved name | |
1528 // "primary, secondary, tertiary" | |
1529 return true; | |
1530 } | |
1531 | |
1532 void EncClass::dump() { | |
1533 output(stderr); | |
1534 } | |
1535 | |
1536 // Write info to output files | |
1537 void EncClass::output(FILE *fp) { | |
1538 fprintf(fp,"EncClass: %s", (_name ? _name : "")); | |
1539 | |
1540 // Output the parameter list | |
1541 _parameter_type.reset(); | |
1542 _parameter_name.reset(); | |
1543 const char *type = _parameter_type.iter(); | |
1544 const char *name = _parameter_name.iter(); | |
1545 fprintf(fp, " ( "); | |
1546 for ( ; (type != NULL) && (name != NULL); | |
1547 (type = _parameter_type.iter()), (name = _parameter_name.iter()) ) { | |
1548 fprintf(fp, " %s %s,", type, name); | |
1549 } | |
1550 fprintf(fp, " ) "); | |
1551 | |
1552 // Output the code block | |
1553 _code.reset(); | |
1554 _rep_vars.reset(); | |
1555 const char *code; | |
1556 while ( (code = _code.iter()) != NULL ) { | |
1557 if ( _code.is_signal(code) ) { | |
1558 // A replacement variable | |
1559 const char *rep_var = _rep_vars.iter(); | |
1560 fprintf(fp,"($%s)", rep_var); | |
1561 } else { | |
1562 // A section of code | |
1563 fprintf(fp,"%s", code); | |
1564 } | |
1565 } | |
1566 | |
1567 } | |
1568 | |
1569 //------------------------------Opcode----------------------------------------- | |
1570 Opcode::Opcode(char *primary, char *secondary, char *tertiary) | |
1571 : _primary(primary), _secondary(secondary), _tertiary(tertiary) { | |
1572 } | |
1573 | |
1574 Opcode::~Opcode() { | |
1575 } | |
1576 | |
1577 Opcode::opcode_type Opcode::as_opcode_type(const char *param) { | |
1578 if( strcmp(param,"primary") == 0 ) { | |
1579 return Opcode::PRIMARY; | |
1580 } | |
1581 else if( strcmp(param,"secondary") == 0 ) { | |
1582 return Opcode::SECONDARY; | |
1583 } | |
1584 else if( strcmp(param,"tertiary") == 0 ) { | |
1585 return Opcode::TERTIARY; | |
1586 } | |
1587 return Opcode::NOT_AN_OPCODE; | |
1588 } | |
1589 | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
1590 bool Opcode::print_opcode(FILE *fp, Opcode::opcode_type desired_opcode) { |
0 | 1591 // Default values previously provided by MachNode::primary()... |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
1592 const char *description = NULL; |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
1593 const char *value = NULL; |
0 | 1594 // Check if user provided any opcode definitions |
1595 if( this != NULL ) { | |
1596 // Update 'value' if user provided a definition in the instruction | |
1597 switch (desired_opcode) { | |
1598 case PRIMARY: | |
1599 description = "primary()"; | |
1600 if( _primary != NULL) { value = _primary; } | |
1601 break; | |
1602 case SECONDARY: | |
1603 description = "secondary()"; | |
1604 if( _secondary != NULL ) { value = _secondary; } | |
1605 break; | |
1606 case TERTIARY: | |
1607 description = "tertiary()"; | |
1608 if( _tertiary != NULL ) { value = _tertiary; } | |
1609 break; | |
1610 default: | |
1611 assert( false, "ShouldNotReachHere();"); | |
1612 break; | |
1613 } | |
1614 } | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
1615 if (value != NULL) { |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
1616 fprintf(fp, "(%s /*%s*/)", value, description); |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
1617 } |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
1618 return value != NULL; |
0 | 1619 } |
1620 | |
1621 void Opcode::dump() { | |
1622 output(stderr); | |
1623 } | |
1624 | |
1625 // Write info to output files | |
1626 void Opcode::output(FILE *fp) { | |
1627 if (_primary != NULL) fprintf(fp,"Primary opcode: %s\n", _primary); | |
1628 if (_secondary != NULL) fprintf(fp,"Secondary opcode: %s\n", _secondary); | |
1629 if (_tertiary != NULL) fprintf(fp,"Tertiary opcode: %s\n", _tertiary); | |
1630 } | |
1631 | |
1632 //------------------------------InsEncode-------------------------------------- | |
1633 InsEncode::InsEncode() { | |
1634 } | |
1635 InsEncode::~InsEncode() { | |
1636 } | |
1637 | |
1638 // Add "encode class name" and its parameters | |
1639 NameAndList *InsEncode::add_encode(char *encoding) { | |
1640 assert( encoding != NULL, "Must provide name for encoding"); | |
1641 | |
1642 // add_parameter(NameList::_signal); | |
1643 NameAndList *encode = new NameAndList(encoding); | |
1644 _encoding.addName((char*)encode); | |
1645 | |
1646 return encode; | |
1647 } | |
1648 | |
1649 // Access the list of encodings | |
1650 void InsEncode::reset() { | |
1651 _encoding.reset(); | |
1652 // _parameter.reset(); | |
1653 } | |
1654 const char* InsEncode::encode_class_iter() { | |
1655 NameAndList *encode_class = (NameAndList*)_encoding.iter(); | |
1656 return ( encode_class != NULL ? encode_class->name() : NULL ); | |
1657 } | |
1658 // Obtain parameter name from zero based index | |
1659 const char *InsEncode::rep_var_name(InstructForm &inst, uint param_no) { | |
1660 NameAndList *params = (NameAndList*)_encoding.current(); | |
1661 assert( params != NULL, "Internal Error"); | |
1662 const char *param = (*params)[param_no]; | |
1663 | |
1664 // Remove '$' if parser placed it there. | |
1665 return ( param != NULL && *param == '$') ? (param+1) : param; | |
1666 } | |
1667 | |
1668 void InsEncode::dump() { | |
1669 output(stderr); | |
1670 } | |
1671 | |
1672 // Write info to output files | |
1673 void InsEncode::output(FILE *fp) { | |
1674 NameAndList *encoding = NULL; | |
1675 const char *parameter = NULL; | |
1676 | |
1677 fprintf(fp,"InsEncode: "); | |
1678 _encoding.reset(); | |
1679 | |
1680 while ( (encoding = (NameAndList*)_encoding.iter()) != 0 ) { | |
1681 // Output the encoding being used | |
1682 fprintf(fp,"%s(", encoding->name() ); | |
1683 | |
1684 // Output its parameter list, if any | |
1685 bool first_param = true; | |
1686 encoding->reset(); | |
1687 while ( (parameter = encoding->iter()) != 0 ) { | |
1688 // Output the ',' between parameters | |
1689 if ( ! first_param ) fprintf(fp,", "); | |
1690 first_param = false; | |
1691 // Output the parameter | |
1692 fprintf(fp,"%s", parameter); | |
1693 } // done with parameters | |
1694 fprintf(fp,") "); | |
1695 } // done with encodings | |
1696 | |
1697 fprintf(fp,"\n"); | |
1698 } | |
1699 | |
1700 //------------------------------Effect----------------------------------------- | |
1701 static int effect_lookup(const char *name) { | |
1702 if(!strcmp(name, "USE")) return Component::USE; | |
1703 if(!strcmp(name, "DEF")) return Component::DEF; | |
1704 if(!strcmp(name, "USE_DEF")) return Component::USE_DEF; | |
1705 if(!strcmp(name, "KILL")) return Component::KILL; | |
1706 if(!strcmp(name, "USE_KILL")) return Component::USE_KILL; | |
1707 if(!strcmp(name, "TEMP")) return Component::TEMP; | |
1708 if(!strcmp(name, "INVALID")) return Component::INVALID; | |
1709 assert( false,"Invalid effect name specified\n"); | |
1710 return Component::INVALID; | |
1711 } | |
1712 | |
1713 Effect::Effect(const char *name) : _name(name), _use_def(effect_lookup(name)) { | |
1714 _ftype = Form::EFF; | |
1715 } | |
1716 Effect::~Effect() { | |
1717 } | |
1718 | |
1719 // Dynamic type check | |
1720 Effect *Effect::is_effect() const { | |
1721 return (Effect*)this; | |
1722 } | |
1723 | |
1724 | |
1725 // True if this component is equal to the parameter. | |
1726 bool Effect::is(int use_def_kill_enum) const { | |
1727 return (_use_def == use_def_kill_enum ? true : false); | |
1728 } | |
1729 // True if this component is used/def'd/kill'd as the parameter suggests. | |
1730 bool Effect::isa(int use_def_kill_enum) const { | |
1731 return (_use_def & use_def_kill_enum) == use_def_kill_enum; | |
1732 } | |
1733 | |
1734 void Effect::dump() { | |
1735 output(stderr); | |
1736 } | |
1737 | |
1738 void Effect::output(FILE *fp) { // Write info to output files | |
1739 fprintf(fp,"Effect: %s\n", (_name?_name:"")); | |
1740 } | |
1741 | |
1742 //------------------------------ExpandRule------------------------------------- | |
1743 ExpandRule::ExpandRule() : _expand_instrs(), | |
1744 _newopconst(cmpstr, hashstr, Form::arena) { | |
1745 _ftype = Form::EXP; | |
1746 } | |
1747 | |
1748 ExpandRule::~ExpandRule() { // Destructor | |
1749 } | |
1750 | |
1751 void ExpandRule::add_instruction(NameAndList *instruction_name_and_operand_list) { | |
1752 _expand_instrs.addName((char*)instruction_name_and_operand_list); | |
1753 } | |
1754 | |
1755 void ExpandRule::reset_instructions() { | |
1756 _expand_instrs.reset(); | |
1757 } | |
1758 | |
1759 NameAndList* ExpandRule::iter_instructions() { | |
1760 return (NameAndList*)_expand_instrs.iter(); | |
1761 } | |
1762 | |
1763 | |
1764 void ExpandRule::dump() { | |
1765 output(stderr); | |
1766 } | |
1767 | |
1768 void ExpandRule::output(FILE *fp) { // Write info to output files | |
1769 NameAndList *expand_instr = NULL; | |
1770 const char *opid = NULL; | |
1771 | |
1772 fprintf(fp,"\nExpand Rule:\n"); | |
1773 | |
1774 // Iterate over the instructions 'node' expands into | |
1775 for(reset_instructions(); (expand_instr = iter_instructions()) != NULL; ) { | |
1776 fprintf(fp,"%s(", expand_instr->name()); | |
1777 | |
1778 // iterate over the operand list | |
1779 for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) { | |
1780 fprintf(fp,"%s ", opid); | |
1781 } | |
1782 fprintf(fp,");\n"); | |
1783 } | |
1784 } | |
1785 | |
1786 //------------------------------RewriteRule------------------------------------ | |
1787 RewriteRule::RewriteRule(char* params, char* block) | |
1788 : _tempParams(params), _tempBlock(block) { }; // Constructor | |
1789 RewriteRule::~RewriteRule() { // Destructor | |
1790 } | |
1791 | |
1792 void RewriteRule::dump() { | |
1793 output(stderr); | |
1794 } | |
1795 | |
1796 void RewriteRule::output(FILE *fp) { // Write info to output files | |
1797 fprintf(fp,"\nRewrite Rule:\n%s\n%s\n", | |
1798 (_tempParams?_tempParams:""), | |
1799 (_tempBlock?_tempBlock:"")); | |
1800 } | |
1801 | |
1802 | |
1803 //==============================MachNodes====================================== | |
1804 //------------------------------MachNodeForm----------------------------------- | |
1805 MachNodeForm::MachNodeForm(char *id) | |
1806 : _ident(id) { | |
1807 } | |
1808 | |
1809 MachNodeForm::~MachNodeForm() { | |
1810 } | |
1811 | |
1812 MachNodeForm *MachNodeForm::is_machnode() const { | |
1813 return (MachNodeForm*)this; | |
1814 } | |
1815 | |
1816 //==============================Operand Classes================================ | |
1817 //------------------------------OpClassForm------------------------------------ | |
1818 OpClassForm::OpClassForm(const char* id) : _ident(id) { | |
1819 _ftype = Form::OPCLASS; | |
1820 } | |
1821 | |
1822 OpClassForm::~OpClassForm() { | |
1823 } | |
1824 | |
1825 bool OpClassForm::ideal_only() const { return 0; } | |
1826 | |
1827 OpClassForm *OpClassForm::is_opclass() const { | |
1828 return (OpClassForm*)this; | |
1829 } | |
1830 | |
1831 Form::InterfaceType OpClassForm::interface_type(FormDict &globals) const { | |
1832 if( _oplst.count() == 0 ) return Form::no_interface; | |
1833 | |
1834 // Check that my operands have the same interface type | |
1835 Form::InterfaceType interface; | |
1836 bool first = true; | |
1837 NameList &op_list = (NameList &)_oplst; | |
1838 op_list.reset(); | |
1839 const char *op_name; | |
1840 while( (op_name = op_list.iter()) != NULL ) { | |
1841 const Form *form = globals[op_name]; | |
1842 OperandForm *operand = form->is_operand(); | |
1843 assert( operand, "Entry in operand class that is not an operand"); | |
1844 if( first ) { | |
1845 first = false; | |
1846 interface = operand->interface_type(globals); | |
1847 } else { | |
1848 interface = (interface == operand->interface_type(globals) ? interface : Form::no_interface); | |
1849 } | |
1850 } | |
1851 return interface; | |
1852 } | |
1853 | |
1854 bool OpClassForm::stack_slots_only(FormDict &globals) const { | |
1855 if( _oplst.count() == 0 ) return false; // how? | |
1856 | |
1857 NameList &op_list = (NameList &)_oplst; | |
1858 op_list.reset(); | |
1859 const char *op_name; | |
1860 while( (op_name = op_list.iter()) != NULL ) { | |
1861 const Form *form = globals[op_name]; | |
1862 OperandForm *operand = form->is_operand(); | |
1863 assert( operand, "Entry in operand class that is not an operand"); | |
1864 if( !operand->stack_slots_only(globals) ) return false; | |
1865 } | |
1866 return true; | |
1867 } | |
1868 | |
1869 | |
1870 void OpClassForm::dump() { | |
1871 output(stderr); | |
1872 } | |
1873 | |
1874 void OpClassForm::output(FILE *fp) { | |
1875 const char *name; | |
1876 fprintf(fp,"\nOperand Class: %s\n", (_ident?_ident:"")); | |
1877 fprintf(fp,"\nCount = %d\n", _oplst.count()); | |
1878 for(_oplst.reset(); (name = _oplst.iter()) != NULL;) { | |
1879 fprintf(fp,"%s, ",name); | |
1880 } | |
1881 fprintf(fp,"\n"); | |
1882 } | |
1883 | |
1884 | |
1885 //==============================Operands======================================= | |
1886 //------------------------------OperandForm------------------------------------ | |
1887 OperandForm::OperandForm(const char* id) | |
1888 : OpClassForm(id), _ideal_only(false), | |
1889 _localNames(cmpstr, hashstr, Form::arena) { | |
1890 _ftype = Form::OPER; | |
1891 | |
1892 _matrule = NULL; | |
1893 _interface = NULL; | |
1894 _attribs = NULL; | |
1895 _predicate = NULL; | |
1896 _constraint= NULL; | |
1897 _construct = NULL; | |
1898 _format = NULL; | |
1899 } | |
1900 OperandForm::OperandForm(const char* id, bool ideal_only) | |
1901 : OpClassForm(id), _ideal_only(ideal_only), | |
1902 _localNames(cmpstr, hashstr, Form::arena) { | |
1903 _ftype = Form::OPER; | |
1904 | |
1905 _matrule = NULL; | |
1906 _interface = NULL; | |
1907 _attribs = NULL; | |
1908 _predicate = NULL; | |
1909 _constraint= NULL; | |
1910 _construct = NULL; | |
1911 _format = NULL; | |
1912 } | |
1913 OperandForm::~OperandForm() { | |
1914 } | |
1915 | |
1916 | |
1917 OperandForm *OperandForm::is_operand() const { | |
1918 return (OperandForm*)this; | |
1919 } | |
1920 | |
1921 bool OperandForm::ideal_only() const { | |
1922 return _ideal_only; | |
1923 } | |
1924 | |
1925 Form::InterfaceType OperandForm::interface_type(FormDict &globals) const { | |
1926 if( _interface == NULL ) return Form::no_interface; | |
1927 | |
1928 return _interface->interface_type(globals); | |
1929 } | |
1930 | |
1931 | |
1932 bool OperandForm::stack_slots_only(FormDict &globals) const { | |
1933 if( _constraint == NULL ) return false; | |
1934 return _constraint->stack_slots_only(); | |
1935 } | |
1936 | |
1937 | |
1938 // Access op_cost attribute or return NULL. | |
1939 const char* OperandForm::cost() { | |
1940 for (Attribute* cur = _attribs; cur != NULL; cur = (Attribute*)cur->_next) { | |
1941 if( strcmp(cur->_ident,AttributeForm::_op_cost) == 0 ) { | |
1942 return cur->_val; | |
1943 } | |
1944 } | |
1945 return NULL; | |
1946 } | |
1947 | |
1948 // Return the number of leaves below this complex operand | |
1949 uint OperandForm::num_leaves() const { | |
1950 if ( ! _matrule) return 0; | |
1951 | |
1952 int num_leaves = _matrule->_numleaves; | |
1953 return num_leaves; | |
1954 } | |
1955 | |
1956 // Return the number of constants contained within this complex operand | |
1957 uint OperandForm::num_consts(FormDict &globals) const { | |
1958 if ( ! _matrule) return 0; | |
1959 | |
1960 // This is a recursive invocation on all operands in the matchrule | |
1961 return _matrule->num_consts(globals); | |
1962 } | |
1963 | |
1964 // Return the number of constants in match rule with specified type | |
1965 uint OperandForm::num_consts(FormDict &globals, Form::DataType type) const { | |
1966 if ( ! _matrule) return 0; | |
1967 | |
1968 // This is a recursive invocation on all operands in the matchrule | |
1969 return _matrule->num_consts(globals, type); | |
1970 } | |
1971 | |
1972 // Return the number of pointer constants contained within this complex operand | |
1973 uint OperandForm::num_const_ptrs(FormDict &globals) const { | |
1974 if ( ! _matrule) return 0; | |
1975 | |
1976 // This is a recursive invocation on all operands in the matchrule | |
1977 return _matrule->num_const_ptrs(globals); | |
1978 } | |
1979 | |
1980 uint OperandForm::num_edges(FormDict &globals) const { | |
1981 uint edges = 0; | |
1982 uint leaves = num_leaves(); | |
1983 uint consts = num_consts(globals); | |
1984 | |
1985 // If we are matching a constant directly, there are no leaves. | |
1986 edges = ( leaves > consts ) ? leaves - consts : 0; | |
1987 | |
1988 // !!!!! | |
1989 // Special case operands that do not have a corresponding ideal node. | |
1990 if( (edges == 0) && (consts == 0) ) { | |
1991 if( constrained_reg_class() != NULL ) { | |
1992 edges = 1; | |
1993 } else { | |
1994 if( _matrule | |
1995 && (_matrule->_lChild == NULL) && (_matrule->_rChild == NULL) ) { | |
1996 const Form *form = globals[_matrule->_opType]; | |
1997 OperandForm *oper = form ? form->is_operand() : NULL; | |
1998 if( oper ) { | |
1999 return oper->num_edges(globals); | |
2000 } | |
2001 } | |
2002 } | |
2003 } | |
2004 | |
2005 return edges; | |
2006 } | |
2007 | |
2008 | |
2009 // Check if this operand is usable for cisc-spilling | |
2010 bool OperandForm::is_cisc_reg(FormDict &globals) const { | |
2011 const char *ideal = ideal_type(globals); | |
2012 bool is_cisc_reg = (ideal && (ideal_to_Reg_type(ideal) != none)); | |
2013 return is_cisc_reg; | |
2014 } | |
2015 | |
2016 bool OpClassForm::is_cisc_mem(FormDict &globals) const { | |
2017 Form::InterfaceType my_interface = interface_type(globals); | |
2018 return (my_interface == memory_interface); | |
2019 } | |
2020 | |
2021 | |
2022 // node matches ideal 'Bool' | |
2023 bool OperandForm::is_ideal_bool() const { | |
2024 if( _matrule == NULL ) return false; | |
2025 | |
2026 return _matrule->is_ideal_bool(); | |
2027 } | |
2028 | |
2029 // Require user's name for an sRegX to be stackSlotX | |
2030 Form::DataType OperandForm::is_user_name_for_sReg() const { | |
2031 DataType data_type = none; | |
2032 if( _ident != NULL ) { | |
2033 if( strcmp(_ident,"stackSlotI") == 0 ) data_type = Form::idealI; | |
2034 else if( strcmp(_ident,"stackSlotP") == 0 ) data_type = Form::idealP; | |
2035 else if( strcmp(_ident,"stackSlotD") == 0 ) data_type = Form::idealD; | |
2036 else if( strcmp(_ident,"stackSlotF") == 0 ) data_type = Form::idealF; | |
2037 else if( strcmp(_ident,"stackSlotL") == 0 ) data_type = Form::idealL; | |
2038 } | |
2039 assert((data_type == none) || (_matrule == NULL), "No match-rule for stackSlotX"); | |
2040 | |
2041 return data_type; | |
2042 } | |
2043 | |
2044 | |
2045 // Return ideal type, if there is a single ideal type for this operand | |
2046 const char *OperandForm::ideal_type(FormDict &globals, RegisterForm *registers) const { | |
2047 const char *type = NULL; | |
2048 if (ideal_only()) type = _ident; | |
2049 else if( _matrule == NULL ) { | |
2050 // Check for condition code register | |
2051 const char *rc_name = constrained_reg_class(); | |
2052 // !!!!! | |
2053 if (rc_name == NULL) return NULL; | |
2054 // !!!!! !!!!! | |
2055 // Check constraints on result's register class | |
2056 if( registers ) { | |
2057 RegClass *reg_class = registers->getRegClass(rc_name); | |
2058 assert( reg_class != NULL, "Register class is not defined"); | |
2059 | |
2060 // Check for ideal type of entries in register class, all are the same type | |
2061 reg_class->reset(); | |
2062 RegDef *reg_def = reg_class->RegDef_iter(); | |
2063 assert( reg_def != NULL, "No entries in register class"); | |
2064 assert( reg_def->_idealtype != NULL, "Did not define ideal type for register"); | |
2065 // Return substring that names the register's ideal type | |
2066 type = reg_def->_idealtype + 3; | |
2067 assert( *(reg_def->_idealtype + 0) == 'O', "Expect Op_ prefix"); | |
2068 assert( *(reg_def->_idealtype + 1) == 'p', "Expect Op_ prefix"); | |
2069 assert( *(reg_def->_idealtype + 2) == '_', "Expect Op_ prefix"); | |
2070 } | |
2071 } | |
2072 else if( _matrule->_lChild == NULL && _matrule->_rChild == NULL ) { | |
2073 // This operand matches a single type, at the top level. | |
2074 // Check for ideal type | |
2075 type = _matrule->_opType; | |
2076 if( strcmp(type,"Bool") == 0 ) | |
2077 return "Bool"; | |
2078 // transitive lookup | |
2079 const Form *frm = globals[type]; | |
2080 OperandForm *op = frm->is_operand(); | |
2081 type = op->ideal_type(globals, registers); | |
2082 } | |
2083 return type; | |
2084 } | |
2085 | |
2086 | |
2087 // If there is a single ideal type for this interface field, return it. | |
2088 const char *OperandForm::interface_ideal_type(FormDict &globals, | |
2089 const char *field) const { | |
2090 const char *ideal_type = NULL; | |
2091 const char *value = NULL; | |
2092 | |
2093 // Check if "field" is valid for this operand's interface | |
2094 if ( ! is_interface_field(field, value) ) return ideal_type; | |
2095 | |
2096 // !!!!! !!!!! !!!!! | |
2097 // If a valid field has a constant value, identify "ConI" or "ConP" or ... | |
2098 | |
2099 // Else, lookup type of field's replacement variable | |
2100 | |
2101 return ideal_type; | |
2102 } | |
2103 | |
2104 | |
2105 RegClass* OperandForm::get_RegClass() const { | |
2106 if (_interface && !_interface->is_RegInterface()) return NULL; | |
2107 return globalAD->get_registers()->getRegClass(constrained_reg_class()); | |
2108 } | |
2109 | |
2110 | |
2111 bool OperandForm::is_bound_register() const { | |
2112 RegClass *reg_class = get_RegClass(); | |
2113 if (reg_class == NULL) return false; | |
2114 | |
2115 const char * name = ideal_type(globalAD->globalNames()); | |
2116 if (name == NULL) return false; | |
2117 | |
2118 int size = 0; | |
2119 if (strcmp(name,"RegFlags")==0) size = 1; | |
2120 if (strcmp(name,"RegI")==0) size = 1; | |
2121 if (strcmp(name,"RegF")==0) size = 1; | |
2122 if (strcmp(name,"RegD")==0) size = 2; | |
2123 if (strcmp(name,"RegL")==0) size = 2; | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2124 if (strcmp(name,"RegN")==0) size = 1; |
0 | 2125 if (strcmp(name,"RegP")==0) size = globalAD->get_preproc_def("_LP64") ? 2 : 1; |
2126 if (size == 0) return false; | |
2127 return size == reg_class->size(); | |
2128 } | |
2129 | |
2130 | |
2131 // Check if this is a valid field for this operand, | |
2132 // Return 'true' if valid, and set the value to the string the user provided. | |
2133 bool OperandForm::is_interface_field(const char *field, | |
2134 const char * &value) const { | |
2135 return false; | |
2136 } | |
2137 | |
2138 | |
2139 // Return register class name if a constraint specifies the register class. | |
2140 const char *OperandForm::constrained_reg_class() const { | |
2141 const char *reg_class = NULL; | |
2142 if ( _constraint ) { | |
2143 // !!!!! | |
2144 Constraint *constraint = _constraint; | |
2145 if ( strcmp(_constraint->_func,"ALLOC_IN_RC") == 0 ) { | |
2146 reg_class = _constraint->_arg; | |
2147 } | |
2148 } | |
2149 | |
2150 return reg_class; | |
2151 } | |
2152 | |
2153 | |
2154 // Return the register class associated with 'leaf'. | |
2155 const char *OperandForm::in_reg_class(uint leaf, FormDict &globals) { | |
2156 const char *reg_class = NULL; // "RegMask::Empty"; | |
2157 | |
2158 if((_matrule == NULL) || (_matrule->is_chain_rule(globals))) { | |
2159 reg_class = constrained_reg_class(); | |
2160 return reg_class; | |
2161 } | |
2162 const char *result = NULL; | |
2163 const char *name = NULL; | |
2164 const char *type = NULL; | |
2165 // iterate through all base operands | |
2166 // until we reach the register that corresponds to "leaf" | |
2167 // This function is not looking for an ideal type. It needs the first | |
2168 // level user type associated with the leaf. | |
2169 for(uint idx = 0;_matrule->base_operand(idx,globals,result,name,type);++idx) { | |
2170 const Form *form = (_localNames[name] ? _localNames[name] : globals[result]); | |
2171 OperandForm *oper = form ? form->is_operand() : NULL; | |
2172 if( oper ) { | |
2173 reg_class = oper->constrained_reg_class(); | |
2174 if( reg_class ) { | |
2175 reg_class = reg_class; | |
2176 } else { | |
2177 // ShouldNotReachHere(); | |
2178 } | |
2179 } else { | |
2180 // ShouldNotReachHere(); | |
2181 } | |
2182 | |
2183 // Increment our target leaf position if current leaf is not a candidate. | |
2184 if( reg_class == NULL) ++leaf; | |
2185 // Exit the loop with the value of reg_class when at the correct index | |
2186 if( idx == leaf ) break; | |
2187 // May iterate through all base operands if reg_class for 'leaf' is NULL | |
2188 } | |
2189 return reg_class; | |
2190 } | |
2191 | |
2192 | |
2193 // Recursive call to construct list of top-level operands. | |
2194 // Implementation does not modify state of internal structures | |
2195 void OperandForm::build_components() { | |
2196 if (_matrule) _matrule->append_components(_localNames, _components); | |
2197 | |
2198 // Add parameters that "do not appear in match rule". | |
2199 const char *name; | |
2200 for (_parameters.reset(); (name = _parameters.iter()) != NULL;) { | |
2201 OperandForm *opForm = (OperandForm*)_localNames[name]; | |
2202 | |
2203 if ( _components.operand_position(name) == -1 ) { | |
2204 _components.insert(name, opForm->_ident, Component::INVALID, false); | |
2205 } | |
2206 } | |
2207 | |
2208 return; | |
2209 } | |
2210 | |
2211 int OperandForm::operand_position(const char *name, int usedef) { | |
2212 return _components.operand_position(name, usedef); | |
2213 } | |
2214 | |
2215 | |
2216 // Return zero-based position in component list, only counting constants; | |
2217 // Return -1 if not in list. | |
2218 int OperandForm::constant_position(FormDict &globals, const Component *last) { | |
605 | 2219 // Iterate through components and count constants preceding 'constant' |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
2220 int position = 0; |
0 | 2221 Component *comp; |
2222 _components.reset(); | |
2223 while( (comp = _components.iter()) != NULL && (comp != last) ) { | |
2224 // Special case for operands that take a single user-defined operand | |
2225 // Skip the initial definition in the component list. | |
2226 if( strcmp(comp->_name,this->_ident) == 0 ) continue; | |
2227 | |
2228 const char *type = comp->_type; | |
2229 // Lookup operand form for replacement variable's type | |
2230 const Form *form = globals[type]; | |
2231 assert( form != NULL, "Component's type not found"); | |
2232 OperandForm *oper = form ? form->is_operand() : NULL; | |
2233 if( oper ) { | |
2234 if( oper->_matrule->is_base_constant(globals) != Form::none ) { | |
2235 ++position; | |
2236 } | |
2237 } | |
2238 } | |
2239 | |
2240 // Check for being passed a component that was not in the list | |
2241 if( comp != last ) position = -1; | |
2242 | |
2243 return position; | |
2244 } | |
2245 // Provide position of constant by "name" | |
2246 int OperandForm::constant_position(FormDict &globals, const char *name) { | |
2247 const Component *comp = _components.search(name); | |
2248 int idx = constant_position( globals, comp ); | |
2249 | |
2250 return idx; | |
2251 } | |
2252 | |
2253 | |
2254 // Return zero-based position in component list, only counting constants; | |
2255 // Return -1 if not in list. | |
2256 int OperandForm::register_position(FormDict &globals, const char *reg_name) { | |
605 | 2257 // Iterate through components and count registers preceding 'last' |
0 | 2258 uint position = 0; |
2259 Component *comp; | |
2260 _components.reset(); | |
2261 while( (comp = _components.iter()) != NULL | |
2262 && (strcmp(comp->_name,reg_name) != 0) ) { | |
2263 // Special case for operands that take a single user-defined operand | |
2264 // Skip the initial definition in the component list. | |
2265 if( strcmp(comp->_name,this->_ident) == 0 ) continue; | |
2266 | |
2267 const char *type = comp->_type; | |
2268 // Lookup operand form for component's type | |
2269 const Form *form = globals[type]; | |
2270 assert( form != NULL, "Component's type not found"); | |
2271 OperandForm *oper = form ? form->is_operand() : NULL; | |
2272 if( oper ) { | |
2273 if( oper->_matrule->is_base_register(globals) ) { | |
2274 ++position; | |
2275 } | |
2276 } | |
2277 } | |
2278 | |
2279 return position; | |
2280 } | |
2281 | |
2282 | |
2283 const char *OperandForm::reduce_result() const { | |
2284 return _ident; | |
2285 } | |
2286 // Return the name of the operand on the right hand side of the binary match | |
2287 // Return NULL if there is no right hand side | |
2288 const char *OperandForm::reduce_right(FormDict &globals) const { | |
2289 return ( _matrule ? _matrule->reduce_right(globals) : NULL ); | |
2290 } | |
2291 | |
2292 // Similar for left | |
2293 const char *OperandForm::reduce_left(FormDict &globals) const { | |
2294 return ( _matrule ? _matrule->reduce_left(globals) : NULL ); | |
2295 } | |
2296 | |
2297 | |
2298 // --------------------------- FILE *output_routines | |
2299 // | |
2300 // Output code for disp_is_oop, if true. | |
2301 void OperandForm::disp_is_oop(FILE *fp, FormDict &globals) { | |
2302 // Check it is a memory interface with a non-user-constant disp field | |
2303 if ( this->_interface == NULL ) return; | |
2304 MemInterface *mem_interface = this->_interface->is_MemInterface(); | |
2305 if ( mem_interface == NULL ) return; | |
2306 const char *disp = mem_interface->_disp; | |
2307 if ( *disp != '$' ) return; | |
2308 | |
2309 // Lookup replacement variable in operand's component list | |
2310 const char *rep_var = disp + 1; | |
2311 const Component *comp = this->_components.search(rep_var); | |
2312 assert( comp != NULL, "Replacement variable not found in components"); | |
2313 // Lookup operand form for replacement variable's type | |
2314 const char *type = comp->_type; | |
2315 Form *form = (Form*)globals[type]; | |
2316 assert( form != NULL, "Replacement variable's type not found"); | |
2317 OperandForm *op = form->is_operand(); | |
2318 assert( op, "Memory Interface 'disp' can only emit an operand form"); | |
2319 // Check if this is a ConP, which may require relocation | |
2320 if ( op->is_base_constant(globals) == Form::idealP ) { | |
2321 // Find the constant's index: _c0, _c1, _c2, ... , _cN | |
2322 uint idx = op->constant_position( globals, rep_var); | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
2323 fprintf(fp," virtual bool disp_is_oop() const {"); |
0 | 2324 fprintf(fp, " return _c%d->isa_oop_ptr();", idx); |
2325 fprintf(fp, " }\n"); | |
2326 } | |
2327 } | |
2328 | |
2329 // Generate code for internal and external format methods | |
2330 // | |
2331 // internal access to reg# node->_idx | |
2332 // access to subsumed constant _c0, _c1, | |
2333 void OperandForm::int_format(FILE *fp, FormDict &globals, uint index) { | |
2334 Form::DataType dtype; | |
2335 if (_matrule && (_matrule->is_base_register(globals) || | |
2336 strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) { | |
2337 // !!!!! !!!!! | |
2338 fprintf(fp, "{ char reg_str[128];\n"); | |
2339 fprintf(fp," ra->dump_register(node,reg_str);\n"); | |
2340 fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); | |
2341 fprintf(fp," }\n"); | |
2342 } else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) { | |
2343 format_constant( fp, index, dtype ); | |
2344 } else if (ideal_to_sReg_type(_ident) != Form::none) { | |
2345 // Special format for Stack Slot Register | |
2346 fprintf(fp, "{ char reg_str[128];\n"); | |
2347 fprintf(fp," ra->dump_register(node,reg_str);\n"); | |
2348 fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); | |
2349 fprintf(fp," }\n"); | |
2350 } else { | |
2351 fprintf(fp,"tty->print(\"No format defined for %s\n\");\n", _ident); | |
2352 fflush(fp); | |
2353 fprintf(stderr,"No format defined for %s\n", _ident); | |
2354 dump(); | |
2355 assert( false,"Internal error:\n output_internal_operand() attempting to output other than a Register or Constant"); | |
2356 } | |
2357 } | |
2358 | |
2359 // Similar to "int_format" but for cases where data is external to operand | |
2360 // external access to reg# node->in(idx)->_idx, | |
2361 void OperandForm::ext_format(FILE *fp, FormDict &globals, uint index) { | |
2362 Form::DataType dtype; | |
2363 if (_matrule && (_matrule->is_base_register(globals) || | |
2364 strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) { | |
2365 fprintf(fp, "{ char reg_str[128];\n"); | |
2366 fprintf(fp," ra->dump_register(node->in(idx"); | |
2367 if ( index != 0 ) fprintf(fp, "+%d",index); | |
2368 fprintf(fp, "),reg_str);\n"); | |
2369 fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); | |
2370 fprintf(fp," }\n"); | |
2371 } else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) { | |
2372 format_constant( fp, index, dtype ); | |
2373 } else if (ideal_to_sReg_type(_ident) != Form::none) { | |
2374 // Special format for Stack Slot Register | |
2375 fprintf(fp, "{ char reg_str[128];\n"); | |
2376 fprintf(fp," ra->dump_register(node->in(idx"); | |
2377 if ( index != 0 ) fprintf(fp, "+%d",index); | |
2378 fprintf(fp, "),reg_str);\n"); | |
2379 fprintf(fp," tty->print(\"%cs\",reg_str);\n",'%'); | |
2380 fprintf(fp," }\n"); | |
2381 } else { | |
2382 fprintf(fp,"tty->print(\"No format defined for %s\n\");\n", _ident); | |
2383 assert( false,"Internal error:\n output_external_operand() attempting to output other than a Register or Constant"); | |
2384 } | |
2385 } | |
2386 | |
2387 void OperandForm::format_constant(FILE *fp, uint const_index, uint const_type) { | |
2388 switch(const_type) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2389 case Form::idealI: fprintf(fp,"st->print(\"#%%d\", _c%d);\n", const_index); break; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2390 case Form::idealP: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2391 case Form::idealN: fprintf(fp,"_c%d->dump_on(st);\n", const_index); break; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2392 case Form::idealL: fprintf(fp,"st->print(\"#%%lld\", _c%d);\n", const_index); break; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2393 case Form::idealF: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
2394 case Form::idealD: fprintf(fp,"st->print(\"#%%f\", _c%d);\n", const_index); break; |
0 | 2395 default: |
2396 assert( false, "ShouldNotReachHere()"); | |
2397 } | |
2398 } | |
2399 | |
2400 // Return the operand form corresponding to the given index, else NULL. | |
2401 OperandForm *OperandForm::constant_operand(FormDict &globals, | |
2402 uint index) { | |
2403 // !!!!! | |
2404 // Check behavior on complex operands | |
2405 uint n_consts = num_consts(globals); | |
2406 if( n_consts > 0 ) { | |
2407 uint i = 0; | |
2408 const char *type; | |
2409 Component *comp; | |
2410 _components.reset(); | |
2411 if ((comp = _components.iter()) == NULL) { | |
2412 assert(n_consts == 1, "Bad component list detected.\n"); | |
2413 // Current operand is THE operand | |
2414 if ( index == 0 ) { | |
2415 return this; | |
2416 } | |
2417 } // end if NULL | |
2418 else { | |
2419 // Skip the first component, it can not be a DEF of a constant | |
2420 do { | |
2421 type = comp->base_type(globals); | |
2422 // Check that "type" is a 'ConI', 'ConP', ... | |
2423 if ( ideal_to_const_type(type) != Form::none ) { | |
2424 // When at correct component, get corresponding Operand | |
2425 if ( index == 0 ) { | |
2426 return globals[comp->_type]->is_operand(); | |
2427 } | |
2428 // Decrement number of constants to go | |
2429 --index; | |
2430 } | |
2431 } while((comp = _components.iter()) != NULL); | |
2432 } | |
2433 } | |
2434 | |
2435 // Did not find a constant for this index. | |
2436 return NULL; | |
2437 } | |
2438 | |
2439 // If this operand has a single ideal type, return its type | |
2440 Form::DataType OperandForm::simple_type(FormDict &globals) const { | |
2441 const char *type_name = ideal_type(globals); | |
2442 Form::DataType type = type_name ? ideal_to_const_type( type_name ) | |
2443 : Form::none; | |
2444 return type; | |
2445 } | |
2446 | |
2447 Form::DataType OperandForm::is_base_constant(FormDict &globals) const { | |
2448 if ( _matrule == NULL ) return Form::none; | |
2449 | |
2450 return _matrule->is_base_constant(globals); | |
2451 } | |
2452 | |
2453 // "true" if this operand is a simple type that is swallowed | |
2454 bool OperandForm::swallowed(FormDict &globals) const { | |
2455 Form::DataType type = simple_type(globals); | |
2456 if( type != Form::none ) { | |
2457 return true; | |
2458 } | |
2459 | |
2460 return false; | |
2461 } | |
2462 | |
2463 // Output code to access the value of the index'th constant | |
2464 void OperandForm::access_constant(FILE *fp, FormDict &globals, | |
2465 uint const_index) { | |
2466 OperandForm *oper = constant_operand(globals, const_index); | |
2467 assert( oper, "Index exceeds number of constants in operand"); | |
2468 Form::DataType dtype = oper->is_base_constant(globals); | |
2469 | |
2470 switch(dtype) { | |
2471 case idealI: fprintf(fp,"_c%d", const_index); break; | |
2472 case idealP: fprintf(fp,"_c%d->get_con()",const_index); break; | |
2473 case idealL: fprintf(fp,"_c%d", const_index); break; | |
2474 case idealF: fprintf(fp,"_c%d", const_index); break; | |
2475 case idealD: fprintf(fp,"_c%d", const_index); break; | |
2476 default: | |
2477 assert( false, "ShouldNotReachHere()"); | |
2478 } | |
2479 } | |
2480 | |
2481 | |
2482 void OperandForm::dump() { | |
2483 output(stderr); | |
2484 } | |
2485 | |
2486 void OperandForm::output(FILE *fp) { | |
2487 fprintf(fp,"\nOperand: %s\n", (_ident?_ident:"")); | |
2488 if (_matrule) _matrule->dump(); | |
2489 if (_interface) _interface->dump(); | |
2490 if (_attribs) _attribs->dump(); | |
2491 if (_predicate) _predicate->dump(); | |
2492 if (_constraint) _constraint->dump(); | |
2493 if (_construct) _construct->dump(); | |
2494 if (_format) _format->dump(); | |
2495 } | |
2496 | |
2497 //------------------------------Constraint------------------------------------- | |
2498 Constraint::Constraint(const char *func, const char *arg) | |
2499 : _func(func), _arg(arg) { | |
2500 } | |
2501 Constraint::~Constraint() { /* not owner of char* */ | |
2502 } | |
2503 | |
2504 bool Constraint::stack_slots_only() const { | |
2505 return strcmp(_func, "ALLOC_IN_RC") == 0 | |
2506 && strcmp(_arg, "stack_slots") == 0; | |
2507 } | |
2508 | |
2509 void Constraint::dump() { | |
2510 output(stderr); | |
2511 } | |
2512 | |
2513 void Constraint::output(FILE *fp) { // Write info to output files | |
2514 assert((_func != NULL && _arg != NULL),"missing constraint function or arg"); | |
2515 fprintf(fp,"Constraint: %s ( %s )\n", _func, _arg); | |
2516 } | |
2517 | |
2518 //------------------------------Predicate-------------------------------------- | |
2519 Predicate::Predicate(char *pr) | |
2520 : _pred(pr) { | |
2521 } | |
2522 Predicate::~Predicate() { | |
2523 } | |
2524 | |
2525 void Predicate::dump() { | |
2526 output(stderr); | |
2527 } | |
2528 | |
2529 void Predicate::output(FILE *fp) { | |
2530 fprintf(fp,"Predicate"); // Write to output files | |
2531 } | |
2532 //------------------------------Interface-------------------------------------- | |
2533 Interface::Interface(const char *name) : _name(name) { | |
2534 } | |
2535 Interface::~Interface() { | |
2536 } | |
2537 | |
2538 Form::InterfaceType Interface::interface_type(FormDict &globals) const { | |
2539 Interface *thsi = (Interface*)this; | |
2540 if ( thsi->is_RegInterface() ) return Form::register_interface; | |
2541 if ( thsi->is_MemInterface() ) return Form::memory_interface; | |
2542 if ( thsi->is_ConstInterface() ) return Form::constant_interface; | |
2543 if ( thsi->is_CondInterface() ) return Form::conditional_interface; | |
2544 | |
2545 return Form::no_interface; | |
2546 } | |
2547 | |
2548 RegInterface *Interface::is_RegInterface() { | |
2549 if ( strcmp(_name,"REG_INTER") != 0 ) | |
2550 return NULL; | |
2551 return (RegInterface*)this; | |
2552 } | |
2553 MemInterface *Interface::is_MemInterface() { | |
2554 if ( strcmp(_name,"MEMORY_INTER") != 0 ) return NULL; | |
2555 return (MemInterface*)this; | |
2556 } | |
2557 ConstInterface *Interface::is_ConstInterface() { | |
2558 if ( strcmp(_name,"CONST_INTER") != 0 ) return NULL; | |
2559 return (ConstInterface*)this; | |
2560 } | |
2561 CondInterface *Interface::is_CondInterface() { | |
2562 if ( strcmp(_name,"COND_INTER") != 0 ) return NULL; | |
2563 return (CondInterface*)this; | |
2564 } | |
2565 | |
2566 | |
2567 void Interface::dump() { | |
2568 output(stderr); | |
2569 } | |
2570 | |
2571 // Write info to output files | |
2572 void Interface::output(FILE *fp) { | |
2573 fprintf(fp,"Interface: %s\n", (_name ? _name : "") ); | |
2574 } | |
2575 | |
2576 //------------------------------RegInterface----------------------------------- | |
2577 RegInterface::RegInterface() : Interface("REG_INTER") { | |
2578 } | |
2579 RegInterface::~RegInterface() { | |
2580 } | |
2581 | |
2582 void RegInterface::dump() { | |
2583 output(stderr); | |
2584 } | |
2585 | |
2586 // Write info to output files | |
2587 void RegInterface::output(FILE *fp) { | |
2588 Interface::output(fp); | |
2589 } | |
2590 | |
2591 //------------------------------ConstInterface--------------------------------- | |
2592 ConstInterface::ConstInterface() : Interface("CONST_INTER") { | |
2593 } | |
2594 ConstInterface::~ConstInterface() { | |
2595 } | |
2596 | |
2597 void ConstInterface::dump() { | |
2598 output(stderr); | |
2599 } | |
2600 | |
2601 // Write info to output files | |
2602 void ConstInterface::output(FILE *fp) { | |
2603 Interface::output(fp); | |
2604 } | |
2605 | |
2606 //------------------------------MemInterface----------------------------------- | |
2607 MemInterface::MemInterface(char *base, char *index, char *scale, char *disp) | |
2608 : Interface("MEMORY_INTER"), _base(base), _index(index), _scale(scale), _disp(disp) { | |
2609 } | |
2610 MemInterface::~MemInterface() { | |
2611 // not owner of any character arrays | |
2612 } | |
2613 | |
2614 void MemInterface::dump() { | |
2615 output(stderr); | |
2616 } | |
2617 | |
2618 // Write info to output files | |
2619 void MemInterface::output(FILE *fp) { | |
2620 Interface::output(fp); | |
2621 if ( _base != NULL ) fprintf(fp," base == %s\n", _base); | |
2622 if ( _index != NULL ) fprintf(fp," index == %s\n", _index); | |
2623 if ( _scale != NULL ) fprintf(fp," scale == %s\n", _scale); | |
2624 if ( _disp != NULL ) fprintf(fp," disp == %s\n", _disp); | |
2625 // fprintf(fp,"\n"); | |
2626 } | |
2627 | |
2628 //------------------------------CondInterface---------------------------------- | |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2629 CondInterface::CondInterface(const char* equal, const char* equal_format, |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2630 const char* not_equal, const char* not_equal_format, |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2631 const char* less, const char* less_format, |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2632 const char* greater_equal, const char* greater_equal_format, |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2633 const char* less_equal, const char* less_equal_format, |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2634 const char* greater, const char* greater_format) |
0 | 2635 : Interface("COND_INTER"), |
415
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2636 _equal(equal), _equal_format(equal_format), |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2637 _not_equal(not_equal), _not_equal_format(not_equal_format), |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2638 _less(less), _less_format(less_format), |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2639 _greater_equal(greater_equal), _greater_equal_format(greater_equal_format), |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2640 _less_equal(less_equal), _less_equal_format(less_equal_format), |
4d9884b01ba6
6754519: don't emit flag fixup for NaN when condition being tested doesn't need it
never
parents:
356
diff
changeset
|
2641 _greater(greater), _greater_format(greater_format) { |
0 | 2642 } |
2643 CondInterface::~CondInterface() { | |
2644 // not owner of any character arrays | |
2645 } | |
2646 | |
2647 void CondInterface::dump() { | |
2648 output(stderr); | |
2649 } | |
2650 | |
2651 // Write info to output files | |
2652 void CondInterface::output(FILE *fp) { | |
2653 Interface::output(fp); | |
2654 if ( _equal != NULL ) fprintf(fp," equal == %s\n", _equal); | |
2655 if ( _not_equal != NULL ) fprintf(fp," not_equal == %s\n", _not_equal); | |
2656 if ( _less != NULL ) fprintf(fp," less == %s\n", _less); | |
2657 if ( _greater_equal != NULL ) fprintf(fp," greater_equal == %s\n", _greater_equal); | |
2658 if ( _less_equal != NULL ) fprintf(fp," less_equal == %s\n", _less_equal); | |
2659 if ( _greater != NULL ) fprintf(fp," greater == %s\n", _greater); | |
2660 // fprintf(fp,"\n"); | |
2661 } | |
2662 | |
2663 //------------------------------ConstructRule---------------------------------- | |
2664 ConstructRule::ConstructRule(char *cnstr) | |
2665 : _construct(cnstr) { | |
2666 } | |
2667 ConstructRule::~ConstructRule() { | |
2668 } | |
2669 | |
2670 void ConstructRule::dump() { | |
2671 output(stderr); | |
2672 } | |
2673 | |
2674 void ConstructRule::output(FILE *fp) { | |
2675 fprintf(fp,"\nConstruct Rule\n"); // Write to output files | |
2676 } | |
2677 | |
2678 | |
2679 //==============================Shared Forms=================================== | |
2680 //------------------------------AttributeForm---------------------------------- | |
2681 int AttributeForm::_insId = 0; // start counter at 0 | |
2682 int AttributeForm::_opId = 0; // start counter at 0 | |
2683 const char* AttributeForm::_ins_cost = "ins_cost"; // required name | |
2684 const char* AttributeForm::_ins_pc_relative = "ins_pc_relative"; | |
2685 const char* AttributeForm::_op_cost = "op_cost"; // required name | |
2686 | |
2687 AttributeForm::AttributeForm(char *attr, int type, char *attrdef) | |
2688 : Form(Form::ATTR), _attrname(attr), _atype(type), _attrdef(attrdef) { | |
2689 if (type==OP_ATTR) { | |
2690 id = ++_opId; | |
2691 } | |
2692 else if (type==INS_ATTR) { | |
2693 id = ++_insId; | |
2694 } | |
2695 else assert( false,""); | |
2696 } | |
2697 AttributeForm::~AttributeForm() { | |
2698 } | |
2699 | |
2700 // Dynamic type check | |
2701 AttributeForm *AttributeForm::is_attribute() const { | |
2702 return (AttributeForm*)this; | |
2703 } | |
2704 | |
2705 | |
2706 // inlined // int AttributeForm::type() { return id;} | |
2707 | |
2708 void AttributeForm::dump() { | |
2709 output(stderr); | |
2710 } | |
2711 | |
2712 void AttributeForm::output(FILE *fp) { | |
2713 if( _attrname && _attrdef ) { | |
2714 fprintf(fp,"\n// AttributeForm \nstatic const int %s = %s;\n", | |
2715 _attrname, _attrdef); | |
2716 } | |
2717 else { | |
2718 fprintf(fp,"\n// AttributeForm missing name %s or definition %s\n", | |
2719 (_attrname?_attrname:""), (_attrdef?_attrdef:"") ); | |
2720 } | |
2721 } | |
2722 | |
2723 //------------------------------Component-------------------------------------- | |
2724 Component::Component(const char *name, const char *type, int usedef) | |
2725 : _name(name), _type(type), _usedef(usedef) { | |
2726 _ftype = Form::COMP; | |
2727 } | |
2728 Component::~Component() { | |
2729 } | |
2730 | |
2731 // True if this component is equal to the parameter. | |
2732 bool Component::is(int use_def_kill_enum) const { | |
2733 return (_usedef == use_def_kill_enum ? true : false); | |
2734 } | |
2735 // True if this component is used/def'd/kill'd as the parameter suggests. | |
2736 bool Component::isa(int use_def_kill_enum) const { | |
2737 return (_usedef & use_def_kill_enum) == use_def_kill_enum; | |
2738 } | |
2739 | |
2740 // Extend this component with additional use/def/kill behavior | |
2741 int Component::promote_use_def_info(int new_use_def) { | |
2742 _usedef |= new_use_def; | |
2743 | |
2744 return _usedef; | |
2745 } | |
2746 | |
2747 // Check the base type of this component, if it has one | |
2748 const char *Component::base_type(FormDict &globals) { | |
2749 const Form *frm = globals[_type]; | |
2750 if (frm == NULL) return NULL; | |
2751 OperandForm *op = frm->is_operand(); | |
2752 if (op == NULL) return NULL; | |
2753 if (op->ideal_only()) return op->_ident; | |
2754 return (char *)op->ideal_type(globals); | |
2755 } | |
2756 | |
2757 void Component::dump() { | |
2758 output(stderr); | |
2759 } | |
2760 | |
2761 void Component::output(FILE *fp) { | |
2762 fprintf(fp,"Component:"); // Write to output files | |
2763 fprintf(fp, " name = %s", _name); | |
2764 fprintf(fp, ", type = %s", _type); | |
2765 const char * usedef = "Undefined Use/Def info"; | |
2766 switch (_usedef) { | |
2767 case USE: usedef = "USE"; break; | |
2768 case USE_DEF: usedef = "USE_DEF"; break; | |
2769 case USE_KILL: usedef = "USE_KILL"; break; | |
2770 case KILL: usedef = "KILL"; break; | |
2771 case TEMP: usedef = "TEMP"; break; | |
2772 case DEF: usedef = "DEF"; break; | |
2773 default: assert(false, "unknown effect"); | |
2774 } | |
2775 fprintf(fp, ", use/def = %s\n", usedef); | |
2776 } | |
2777 | |
2778 | |
2779 //------------------------------ComponentList--------------------------------- | |
2780 ComponentList::ComponentList() : NameList(), _matchcnt(0) { | |
2781 } | |
2782 ComponentList::~ComponentList() { | |
2783 // // This list may not own its elements if copied via assignment | |
2784 // Component *component; | |
2785 // for (reset(); (component = iter()) != NULL;) { | |
2786 // delete component; | |
2787 // } | |
2788 } | |
2789 | |
2790 void ComponentList::insert(Component *component, bool mflag) { | |
2791 NameList::addName((char *)component); | |
2792 if(mflag) _matchcnt++; | |
2793 } | |
2794 void ComponentList::insert(const char *name, const char *opType, int usedef, | |
2795 bool mflag) { | |
2796 Component * component = new Component(name, opType, usedef); | |
2797 insert(component, mflag); | |
2798 } | |
2799 Component *ComponentList::current() { return (Component*)NameList::current(); } | |
2800 Component *ComponentList::iter() { return (Component*)NameList::iter(); } | |
2801 Component *ComponentList::match_iter() { | |
2802 if(_iter < _matchcnt) return (Component*)NameList::iter(); | |
2803 return NULL; | |
2804 } | |
2805 Component *ComponentList::post_match_iter() { | |
2806 Component *comp = iter(); | |
2807 // At end of list? | |
2808 if ( comp == NULL ) { | |
2809 return comp; | |
2810 } | |
2811 // In post-match components? | |
2812 if (_iter > match_count()-1) { | |
2813 return comp; | |
2814 } | |
2815 | |
2816 return post_match_iter(); | |
2817 } | |
2818 | |
2819 void ComponentList::reset() { NameList::reset(); } | |
2820 int ComponentList::count() { return NameList::count(); } | |
2821 | |
2822 Component *ComponentList::operator[](int position) { | |
2823 // Shortcut complete iteration if there are not enough entries | |
2824 if (position >= count()) return NULL; | |
2825 | |
2826 int index = 0; | |
2827 Component *component = NULL; | |
2828 for (reset(); (component = iter()) != NULL;) { | |
2829 if (index == position) { | |
2830 return component; | |
2831 } | |
2832 ++index; | |
2833 } | |
2834 | |
2835 return NULL; | |
2836 } | |
2837 | |
2838 const Component *ComponentList::search(const char *name) { | |
2839 PreserveIter pi(this); | |
2840 reset(); | |
2841 for( Component *comp = NULL; ((comp = iter()) != NULL); ) { | |
2842 if( strcmp(comp->_name,name) == 0 ) return comp; | |
2843 } | |
2844 | |
2845 return NULL; | |
2846 } | |
2847 | |
2848 // Return number of USEs + number of DEFs | |
2849 // When there are no components, or the first component is a USE, | |
2850 // then we add '1' to hold a space for the 'result' operand. | |
2851 int ComponentList::num_operands() { | |
2852 PreserveIter pi(this); | |
2853 uint count = 1; // result operand | |
2854 uint position = 0; | |
2855 | |
2856 Component *component = NULL; | |
2857 for( reset(); (component = iter()) != NULL; ++position ) { | |
2858 if( component->isa(Component::USE) || | |
2859 ( position == 0 && (! component->isa(Component::DEF))) ) { | |
2860 ++count; | |
2861 } | |
2862 } | |
2863 | |
2864 return count; | |
2865 } | |
2866 | |
2867 // Return zero-based position in list; -1 if not in list. | |
2868 // if parameter 'usedef' is ::USE, it will match USE, USE_DEF, ... | |
2869 int ComponentList::operand_position(const char *name, int usedef) { | |
2870 PreserveIter pi(this); | |
2871 int position = 0; | |
2872 int num_opnds = num_operands(); | |
2873 Component *component; | |
2874 Component* preceding_non_use = NULL; | |
2875 Component* first_def = NULL; | |
2876 for (reset(); (component = iter()) != NULL; ++position) { | |
2877 // When the first component is not a DEF, | |
2878 // leave space for the result operand! | |
2879 if ( position==0 && (! component->isa(Component::DEF)) ) { | |
2880 ++position; | |
2881 ++num_opnds; | |
2882 } | |
2883 if (strcmp(name, component->_name)==0 && (component->isa(usedef))) { | |
2884 // When the first entry in the component list is a DEF and a USE | |
2885 // Treat them as being separate, a DEF first, then a USE | |
2886 if( position==0 | |
2887 && usedef==Component::USE && component->isa(Component::DEF) ) { | |
2888 assert(position+1 < num_opnds, "advertised index in bounds"); | |
2889 return position+1; | |
2890 } else { | |
2891 if( preceding_non_use && strcmp(component->_name, preceding_non_use->_name) ) { | |
2892 fprintf(stderr, "the name '%s' should not precede the name '%s'\n", preceding_non_use->_name, name); | |
2893 } | |
2894 if( position >= num_opnds ) { | |
2895 fprintf(stderr, "the name '%s' is too late in its name list\n", name); | |
2896 } | |
2897 assert(position < num_opnds, "advertised index in bounds"); | |
2898 return position; | |
2899 } | |
2900 } | |
2901 if( component->isa(Component::DEF) | |
2902 && component->isa(Component::USE) ) { | |
2903 ++position; | |
2904 if( position != 1 ) --position; // only use two slots for the 1st USE_DEF | |
2905 } | |
2906 if( component->isa(Component::DEF) && !first_def ) { | |
2907 first_def = component; | |
2908 } | |
2909 if( !component->isa(Component::USE) && component != first_def ) { | |
2910 preceding_non_use = component; | |
2911 } else if( preceding_non_use && !strcmp(component->_name, preceding_non_use->_name) ) { | |
2912 preceding_non_use = NULL; | |
2913 } | |
2914 } | |
2915 return Not_in_list; | |
2916 } | |
2917 | |
2918 // Find position for this name, regardless of use/def information | |
2919 int ComponentList::operand_position(const char *name) { | |
2920 PreserveIter pi(this); | |
2921 int position = 0; | |
2922 Component *component; | |
2923 for (reset(); (component = iter()) != NULL; ++position) { | |
2924 // When the first component is not a DEF, | |
2925 // leave space for the result operand! | |
2926 if ( position==0 && (! component->isa(Component::DEF)) ) { | |
2927 ++position; | |
2928 } | |
2929 if (strcmp(name, component->_name)==0) { | |
2930 return position; | |
2931 } | |
2932 if( component->isa(Component::DEF) | |
2933 && component->isa(Component::USE) ) { | |
2934 ++position; | |
2935 if( position != 1 ) --position; // only use two slots for the 1st USE_DEF | |
2936 } | |
2937 } | |
2938 return Not_in_list; | |
2939 } | |
2940 | |
2941 int ComponentList::operand_position_format(const char *name) { | |
2942 PreserveIter pi(this); | |
2943 int first_position = operand_position(name); | |
2944 int use_position = operand_position(name, Component::USE); | |
2945 | |
2946 return ((first_position < use_position) ? use_position : first_position); | |
2947 } | |
2948 | |
2949 int ComponentList::label_position() { | |
2950 PreserveIter pi(this); | |
2951 int position = 0; | |
2952 reset(); | |
2953 for( Component *comp; (comp = iter()) != NULL; ++position) { | |
2954 // When the first component is not a DEF, | |
2955 // leave space for the result operand! | |
2956 if ( position==0 && (! comp->isa(Component::DEF)) ) { | |
2957 ++position; | |
2958 } | |
2959 if (strcmp(comp->_type, "label")==0) { | |
2960 return position; | |
2961 } | |
2962 if( comp->isa(Component::DEF) | |
2963 && comp->isa(Component::USE) ) { | |
2964 ++position; | |
2965 if( position != 1 ) --position; // only use two slots for the 1st USE_DEF | |
2966 } | |
2967 } | |
2968 | |
2969 return -1; | |
2970 } | |
2971 | |
2972 int ComponentList::method_position() { | |
2973 PreserveIter pi(this); | |
2974 int position = 0; | |
2975 reset(); | |
2976 for( Component *comp; (comp = iter()) != NULL; ++position) { | |
2977 // When the first component is not a DEF, | |
2978 // leave space for the result operand! | |
2979 if ( position==0 && (! comp->isa(Component::DEF)) ) { | |
2980 ++position; | |
2981 } | |
2982 if (strcmp(comp->_type, "method")==0) { | |
2983 return position; | |
2984 } | |
2985 if( comp->isa(Component::DEF) | |
2986 && comp->isa(Component::USE) ) { | |
2987 ++position; | |
2988 if( position != 1 ) --position; // only use two slots for the 1st USE_DEF | |
2989 } | |
2990 } | |
2991 | |
2992 return -1; | |
2993 } | |
2994 | |
2995 void ComponentList::dump() { output(stderr); } | |
2996 | |
2997 void ComponentList::output(FILE *fp) { | |
2998 PreserveIter pi(this); | |
2999 fprintf(fp, "\n"); | |
3000 Component *component; | |
3001 for (reset(); (component = iter()) != NULL;) { | |
3002 component->output(fp); | |
3003 } | |
3004 fprintf(fp, "\n"); | |
3005 } | |
3006 | |
3007 //------------------------------MatchNode-------------------------------------- | |
3008 MatchNode::MatchNode(ArchDesc &ad, const char *result, const char *mexpr, | |
3009 const char *opType, MatchNode *lChild, MatchNode *rChild) | |
3010 : _AD(ad), _result(result), _name(mexpr), _opType(opType), | |
3011 _lChild(lChild), _rChild(rChild), _internalop(0), _numleaves(0), | |
3012 _commutative_id(0) { | |
3013 _numleaves = (lChild ? lChild->_numleaves : 0) | |
3014 + (rChild ? rChild->_numleaves : 0); | |
3015 } | |
3016 | |
3017 MatchNode::MatchNode(ArchDesc &ad, MatchNode& mnode) | |
3018 : _AD(ad), _result(mnode._result), _name(mnode._name), | |
3019 _opType(mnode._opType), _lChild(mnode._lChild), _rChild(mnode._rChild), | |
3020 _internalop(0), _numleaves(mnode._numleaves), | |
3021 _commutative_id(mnode._commutative_id) { | |
3022 } | |
3023 | |
3024 MatchNode::MatchNode(ArchDesc &ad, MatchNode& mnode, int clone) | |
3025 : _AD(ad), _result(mnode._result), _name(mnode._name), | |
3026 _opType(mnode._opType), | |
3027 _internalop(0), _numleaves(mnode._numleaves), | |
3028 _commutative_id(mnode._commutative_id) { | |
3029 if (mnode._lChild) { | |
3030 _lChild = new MatchNode(ad, *mnode._lChild, clone); | |
3031 } else { | |
3032 _lChild = NULL; | |
3033 } | |
3034 if (mnode._rChild) { | |
3035 _rChild = new MatchNode(ad, *mnode._rChild, clone); | |
3036 } else { | |
3037 _rChild = NULL; | |
3038 } | |
3039 } | |
3040 | |
3041 MatchNode::~MatchNode() { | |
3042 // // This node may not own its children if copied via assignment | |
3043 // if( _lChild ) delete _lChild; | |
3044 // if( _rChild ) delete _rChild; | |
3045 } | |
3046 | |
3047 bool MatchNode::find_type(const char *type, int &position) const { | |
3048 if ( (_lChild != NULL) && (_lChild->find_type(type, position)) ) return true; | |
3049 if ( (_rChild != NULL) && (_rChild->find_type(type, position)) ) return true; | |
3050 | |
3051 if (strcmp(type,_opType)==0) { | |
3052 return true; | |
3053 } else { | |
3054 ++position; | |
3055 } | |
3056 return false; | |
3057 } | |
3058 | |
3059 // Recursive call collecting info on top-level operands, not transitive. | |
3060 // Implementation does not modify state of internal structures. | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3061 void MatchNode::append_components(FormDict& locals, ComponentList& components, |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3062 bool def_flag) const { |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3063 int usedef = def_flag ? Component::DEF : Component::USE; |
0 | 3064 FormDict &globals = _AD.globalNames(); |
3065 | |
3066 assert (_name != NULL, "MatchNode::build_components encountered empty node\n"); | |
3067 // Base case | |
3068 if (_lChild==NULL && _rChild==NULL) { | |
3069 // If _opType is not an operation, do not build a component for it ##### | |
3070 const Form *f = globals[_opType]; | |
3071 if( f != NULL ) { | |
3072 // Add non-ideals that are operands, operand-classes, | |
3073 if( ! f->ideal_only() | |
3074 && (f->is_opclass() || f->is_operand()) ) { | |
3075 components.insert(_name, _opType, usedef, true); | |
3076 } | |
3077 } | |
3078 return; | |
3079 } | |
3080 // Promote results of "Set" to DEF | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3081 bool tmpdef_flag = (!strcmp(_opType, "Set")) ? true : false; |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3082 if (_lChild) _lChild->append_components(locals, components, tmpdef_flag); |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3083 tmpdef_flag = false; // only applies to component immediately following 'Set' |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3084 if (_rChild) _rChild->append_components(locals, components, tmpdef_flag); |
0 | 3085 } |
3086 | |
3087 // Find the n'th base-operand in the match node, | |
3088 // recursively investigates match rules of user-defined operands. | |
3089 // | |
3090 // Implementation does not modify state of internal structures since they | |
3091 // can be shared. | |
3092 bool MatchNode::base_operand(uint &position, FormDict &globals, | |
3093 const char * &result, const char * &name, | |
3094 const char * &opType) const { | |
3095 assert (_name != NULL, "MatchNode::base_operand encountered empty node\n"); | |
3096 // Base case | |
3097 if (_lChild==NULL && _rChild==NULL) { | |
3098 // Check for special case: "Universe", "label" | |
3099 if (strcmp(_opType,"Universe") == 0 || strcmp(_opType,"label")==0 ) { | |
3100 if (position == 0) { | |
3101 result = _result; | |
3102 name = _name; | |
3103 opType = _opType; | |
3104 return 1; | |
3105 } else { | |
3106 -- position; | |
3107 return 0; | |
3108 } | |
3109 } | |
3110 | |
3111 const Form *form = globals[_opType]; | |
3112 MatchNode *matchNode = NULL; | |
3113 // Check for user-defined type | |
3114 if (form) { | |
3115 // User operand or instruction? | |
3116 OperandForm *opForm = form->is_operand(); | |
3117 InstructForm *inForm = form->is_instruction(); | |
3118 if ( opForm ) { | |
3119 matchNode = (MatchNode*)opForm->_matrule; | |
3120 } else if ( inForm ) { | |
3121 matchNode = (MatchNode*)inForm->_matrule; | |
3122 } | |
3123 } | |
3124 // if this is user-defined, recurse on match rule | |
3125 // User-defined operand and instruction forms have a match-rule. | |
3126 if (matchNode) { | |
3127 return (matchNode->base_operand(position,globals,result,name,opType)); | |
3128 } else { | |
3129 // Either not a form, or a system-defined form (no match rule). | |
3130 if (position==0) { | |
3131 result = _result; | |
3132 name = _name; | |
3133 opType = _opType; | |
3134 return 1; | |
3135 } else { | |
3136 --position; | |
3137 return 0; | |
3138 } | |
3139 } | |
3140 | |
3141 } else { | |
3142 // Examine the left child and right child as well | |
3143 if (_lChild) { | |
3144 if (_lChild->base_operand(position, globals, result, name, opType)) | |
3145 return 1; | |
3146 } | |
3147 | |
3148 if (_rChild) { | |
3149 if (_rChild->base_operand(position, globals, result, name, opType)) | |
3150 return 1; | |
3151 } | |
3152 } | |
3153 | |
3154 return 0; | |
3155 } | |
3156 | |
3157 // Recursive call on all operands' match rules in my match rule. | |
3158 uint MatchNode::num_consts(FormDict &globals) const { | |
3159 uint index = 0; | |
3160 uint num_consts = 0; | |
3161 const char *result; | |
3162 const char *name; | |
3163 const char *opType; | |
3164 | |
3165 for (uint position = index; | |
3166 base_operand(position,globals,result,name,opType); position = index) { | |
3167 ++index; | |
3168 if( ideal_to_const_type(opType) ) num_consts++; | |
3169 } | |
3170 | |
3171 return num_consts; | |
3172 } | |
3173 | |
3174 // Recursive call on all operands' match rules in my match rule. | |
3175 // Constants in match rule subtree with specified type | |
3176 uint MatchNode::num_consts(FormDict &globals, Form::DataType type) const { | |
3177 uint index = 0; | |
3178 uint num_consts = 0; | |
3179 const char *result; | |
3180 const char *name; | |
3181 const char *opType; | |
3182 | |
3183 for (uint position = index; | |
3184 base_operand(position,globals,result,name,opType); position = index) { | |
3185 ++index; | |
3186 if( ideal_to_const_type(opType) == type ) num_consts++; | |
3187 } | |
3188 | |
3189 return num_consts; | |
3190 } | |
3191 | |
3192 // Recursive call on all operands' match rules in my match rule. | |
3193 uint MatchNode::num_const_ptrs(FormDict &globals) const { | |
3194 return num_consts( globals, Form::idealP ); | |
3195 } | |
3196 | |
3197 bool MatchNode::sets_result() const { | |
3198 return ( (strcmp(_name,"Set") == 0) ? true : false ); | |
3199 } | |
3200 | |
3201 const char *MatchNode::reduce_right(FormDict &globals) const { | |
3202 // If there is no right reduction, return NULL. | |
3203 const char *rightStr = NULL; | |
3204 | |
3205 // If we are a "Set", start from the right child. | |
3206 const MatchNode *const mnode = sets_result() ? | |
3207 (const MatchNode *const)this->_rChild : | |
3208 (const MatchNode *const)this; | |
3209 | |
3210 // If our right child exists, it is the right reduction | |
3211 if ( mnode->_rChild ) { | |
3212 rightStr = mnode->_rChild->_internalop ? mnode->_rChild->_internalop | |
3213 : mnode->_rChild->_opType; | |
3214 } | |
3215 // Else, May be simple chain rule: (Set dst operand_form), rightStr=NULL; | |
3216 return rightStr; | |
3217 } | |
3218 | |
3219 const char *MatchNode::reduce_left(FormDict &globals) const { | |
3220 // If there is no left reduction, return NULL. | |
3221 const char *leftStr = NULL; | |
3222 | |
3223 // If we are a "Set", start from the right child. | |
3224 const MatchNode *const mnode = sets_result() ? | |
3225 (const MatchNode *const)this->_rChild : | |
3226 (const MatchNode *const)this; | |
3227 | |
3228 // If our left child exists, it is the left reduction | |
3229 if ( mnode->_lChild ) { | |
3230 leftStr = mnode->_lChild->_internalop ? mnode->_lChild->_internalop | |
3231 : mnode->_lChild->_opType; | |
3232 } else { | |
3233 // May be simple chain rule: (Set dst operand_form_source) | |
3234 if ( sets_result() ) { | |
3235 OperandForm *oper = globals[mnode->_opType]->is_operand(); | |
3236 if( oper ) { | |
3237 leftStr = mnode->_opType; | |
3238 } | |
3239 } | |
3240 } | |
3241 return leftStr; | |
3242 } | |
3243 | |
3244 //------------------------------count_instr_names------------------------------ | |
3245 // Count occurrences of operands names in the leaves of the instruction | |
3246 // match rule. | |
3247 void MatchNode::count_instr_names( Dict &names ) { | |
3248 if( !this ) return; | |
3249 if( _lChild ) _lChild->count_instr_names(names); | |
3250 if( _rChild ) _rChild->count_instr_names(names); | |
3251 if( !_lChild && !_rChild ) { | |
3252 uintptr_t cnt = (uintptr_t)names[_name]; | |
3253 cnt++; // One more name found | |
3254 names.Insert(_name,(void*)cnt); | |
3255 } | |
3256 } | |
3257 | |
3258 //------------------------------build_instr_pred------------------------------- | |
3259 // Build a path to 'name' in buf. Actually only build if cnt is zero, so we | |
3260 // can skip some leading instances of 'name'. | |
3261 int MatchNode::build_instr_pred( char *buf, const char *name, int cnt ) { | |
3262 if( _lChild ) { | |
3263 if( !cnt ) strcpy( buf, "_kids[0]->" ); | |
3264 cnt = _lChild->build_instr_pred( buf+strlen(buf), name, cnt ); | |
3265 if( cnt < 0 ) return cnt; // Found it, all done | |
3266 } | |
3267 if( _rChild ) { | |
3268 if( !cnt ) strcpy( buf, "_kids[1]->" ); | |
3269 cnt = _rChild->build_instr_pred( buf+strlen(buf), name, cnt ); | |
3270 if( cnt < 0 ) return cnt; // Found it, all done | |
3271 } | |
3272 if( !_lChild && !_rChild ) { // Found a leaf | |
3273 // Wrong name? Give up... | |
3274 if( strcmp(name,_name) ) return cnt; | |
3275 if( !cnt ) strcpy(buf,"_leaf"); | |
3276 return cnt-1; | |
3277 } | |
3278 return cnt; | |
3279 } | |
3280 | |
3281 | |
3282 //------------------------------build_internalop------------------------------- | |
3283 // Build string representation of subtree | |
3284 void MatchNode::build_internalop( ) { | |
3285 char *iop, *subtree; | |
3286 const char *lstr, *rstr; | |
3287 // Build string representation of subtree | |
3288 // Operation lchildType rchildType | |
3289 int len = (int)strlen(_opType) + 4; | |
3290 lstr = (_lChild) ? ((_lChild->_internalop) ? | |
3291 _lChild->_internalop : _lChild->_opType) : ""; | |
3292 rstr = (_rChild) ? ((_rChild->_internalop) ? | |
3293 _rChild->_internalop : _rChild->_opType) : ""; | |
3294 len += (int)strlen(lstr) + (int)strlen(rstr); | |
3295 subtree = (char *)malloc(len); | |
3296 sprintf(subtree,"_%s_%s_%s", _opType, lstr, rstr); | |
3297 // Hash the subtree string in _internalOps; if a name exists, use it | |
3298 iop = (char *)_AD._internalOps[subtree]; | |
3299 // Else create a unique name, and add it to the hash table | |
3300 if (iop == NULL) { | |
3301 iop = subtree; | |
3302 _AD._internalOps.Insert(subtree, iop); | |
3303 _AD._internalOpNames.addName(iop); | |
3304 _AD._internalMatch.Insert(iop, this); | |
3305 } | |
3306 // Add the internal operand name to the MatchNode | |
3307 _internalop = iop; | |
3308 _result = iop; | |
3309 } | |
3310 | |
3311 | |
3312 void MatchNode::dump() { | |
3313 output(stderr); | |
3314 } | |
3315 | |
3316 void MatchNode::output(FILE *fp) { | |
3317 if (_lChild==0 && _rChild==0) { | |
3318 fprintf(fp," %s",_name); // operand | |
3319 } | |
3320 else { | |
3321 fprintf(fp," (%s ",_name); // " (opcodeName " | |
3322 if(_lChild) _lChild->output(fp); // left operand | |
3323 if(_rChild) _rChild->output(fp); // right operand | |
3324 fprintf(fp,")"); // ")" | |
3325 } | |
3326 } | |
3327 | |
3328 int MatchNode::needs_ideal_memory_edge(FormDict &globals) const { | |
3329 static const char *needs_ideal_memory_list[] = { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3330 "StoreI","StoreL","StoreP","StoreN","StoreD","StoreF" , |
0 | 3331 "StoreB","StoreC","Store" ,"StoreFP", |
624 | 3332 "LoadI", "LoadUI2L", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" , |
3333 "LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load" , | |
0 | 3334 "Store4I","Store2I","Store2L","Store2D","Store4F","Store2F","Store16B", |
3335 "Store8B","Store4B","Store8C","Store4C","Store2C", | |
3336 "Load4I" ,"Load2I" ,"Load2L" ,"Load2D" ,"Load4F" ,"Load2F" ,"Load16B" , | |
3337 "Load8B" ,"Load4B" ,"Load8C" ,"Load4C" ,"Load2C" ,"Load8S", "Load4S","Load2S", | |
164
c436414a719e
6703890: Compressed Oops: add LoadNKlass node to generate narrow oops (32-bits) compare instructions
kvn
parents:
113
diff
changeset
|
3338 "LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned", |
0 | 3339 "LoadPLocked", "LoadLLocked", |
420
a1980da045cc
6462850: generate biased locking code in C2 ideal graph
kvn
parents:
415
diff
changeset
|
3340 "StorePConditional", "StoreIConditional", "StoreLConditional", |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3341 "CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN", |
0 | 3342 "StoreCM", |
3343 "ClearArray" | |
3344 }; | |
3345 int cnt = sizeof(needs_ideal_memory_list)/sizeof(char*); | |
3346 if( strcmp(_opType,"PrefetchRead")==0 || strcmp(_opType,"PrefetchWrite")==0 ) | |
3347 return 1; | |
3348 if( _lChild ) { | |
3349 const char *opType = _lChild->_opType; | |
3350 for( int i=0; i<cnt; i++ ) | |
3351 if( strcmp(opType,needs_ideal_memory_list[i]) == 0 ) | |
3352 return 1; | |
3353 if( _lChild->needs_ideal_memory_edge(globals) ) | |
3354 return 1; | |
3355 } | |
3356 if( _rChild ) { | |
3357 const char *opType = _rChild->_opType; | |
3358 for( int i=0; i<cnt; i++ ) | |
3359 if( strcmp(opType,needs_ideal_memory_list[i]) == 0 ) | |
3360 return 1; | |
3361 if( _rChild->needs_ideal_memory_edge(globals) ) | |
3362 return 1; | |
3363 } | |
3364 | |
3365 return 0; | |
3366 } | |
3367 | |
3368 // TRUE if defines a derived oop, and so needs a base oop edge present | |
3369 // post-matching. | |
3370 int MatchNode::needs_base_oop_edge() const { | |
3371 if( !strcmp(_opType,"AddP") ) return 1; | |
3372 if( strcmp(_opType,"Set") ) return 0; | |
3373 return !strcmp(_rChild->_opType,"AddP"); | |
3374 } | |
3375 | |
3376 int InstructForm::needs_base_oop_edge(FormDict &globals) const { | |
3377 if( is_simple_chain_rule(globals) ) { | |
3378 const char *src = _matrule->_rChild->_opType; | |
3379 OperandForm *src_op = globals[src]->is_operand(); | |
3380 assert( src_op, "Not operand class of chain rule" ); | |
3381 return src_op->_matrule ? src_op->_matrule->needs_base_oop_edge() : 0; | |
3382 } // Else check instruction | |
3383 | |
3384 return _matrule ? _matrule->needs_base_oop_edge() : 0; | |
3385 } | |
3386 | |
3387 | |
3388 //-------------------------cisc spilling methods------------------------------- | |
3389 // helper routines and methods for detecting cisc-spilling instructions | |
3390 //-------------------------cisc_spill_merge------------------------------------ | |
3391 int MatchNode::cisc_spill_merge(int left_spillable, int right_spillable) { | |
3392 int cisc_spillable = Maybe_cisc_spillable; | |
3393 | |
3394 // Combine results of left and right checks | |
3395 if( (left_spillable == Maybe_cisc_spillable) && (right_spillable == Maybe_cisc_spillable) ) { | |
3396 // neither side is spillable, nor prevents cisc spilling | |
3397 cisc_spillable = Maybe_cisc_spillable; | |
3398 } | |
3399 else if( (left_spillable == Maybe_cisc_spillable) && (right_spillable > Maybe_cisc_spillable) ) { | |
3400 // right side is spillable | |
3401 cisc_spillable = right_spillable; | |
3402 } | |
3403 else if( (right_spillable == Maybe_cisc_spillable) && (left_spillable > Maybe_cisc_spillable) ) { | |
3404 // left side is spillable | |
3405 cisc_spillable = left_spillable; | |
3406 } | |
3407 else if( (left_spillable == Not_cisc_spillable) || (right_spillable == Not_cisc_spillable) ) { | |
3408 // left or right prevents cisc spilling this instruction | |
3409 cisc_spillable = Not_cisc_spillable; | |
3410 } | |
3411 else { | |
3412 // Only allow one to spill | |
3413 cisc_spillable = Not_cisc_spillable; | |
3414 } | |
3415 | |
3416 return cisc_spillable; | |
3417 } | |
3418 | |
3419 //-------------------------root_ops_match-------------------------------------- | |
3420 bool static root_ops_match(FormDict &globals, const char *op1, const char *op2) { | |
3421 // Base Case: check that the current operands/operations match | |
3422 assert( op1, "Must have op's name"); | |
3423 assert( op2, "Must have op's name"); | |
3424 const Form *form1 = globals[op1]; | |
3425 const Form *form2 = globals[op2]; | |
3426 | |
3427 return (form1 == form2); | |
3428 } | |
3429 | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3430 //-------------------------cisc_spill_match_node------------------------------- |
0 | 3431 // Recursively check two MatchRules for legal conversion via cisc-spilling |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3432 int MatchNode::cisc_spill_match(FormDict& globals, RegisterForm* registers, MatchNode* mRule2, const char* &operand, const char* ®_type) { |
0 | 3433 int cisc_spillable = Maybe_cisc_spillable; |
3434 int left_spillable = Maybe_cisc_spillable; | |
3435 int right_spillable = Maybe_cisc_spillable; | |
3436 | |
3437 // Check that each has same number of operands at this level | |
3438 if( (_lChild && !(mRule2->_lChild)) || (_rChild && !(mRule2->_rChild)) ) | |
3439 return Not_cisc_spillable; | |
3440 | |
3441 // Base Case: check that the current operands/operations match | |
3442 // or are CISC spillable | |
3443 assert( _opType, "Must have _opType"); | |
3444 assert( mRule2->_opType, "Must have _opType"); | |
3445 const Form *form = globals[_opType]; | |
3446 const Form *form2 = globals[mRule2->_opType]; | |
3447 if( form == form2 ) { | |
3448 cisc_spillable = Maybe_cisc_spillable; | |
3449 } else { | |
3450 const InstructForm *form2_inst = form2 ? form2->is_instruction() : NULL; | |
3451 const char *name_left = mRule2->_lChild ? mRule2->_lChild->_opType : NULL; | |
3452 const char *name_right = mRule2->_rChild ? mRule2->_rChild->_opType : NULL; | |
624 | 3453 DataType data_type = Form::none; |
3454 if (form->is_operand()) { | |
3455 // Make sure the loadX matches the type of the reg | |
3456 data_type = form->ideal_to_Reg_type(form->is_operand()->ideal_type(globals)); | |
3457 } | |
0 | 3458 // Detect reg vs (loadX memory) |
3459 if( form->is_cisc_reg(globals) | |
3460 && form2_inst | |
624 | 3461 && data_type != Form::none |
3462 && (is_load_from_memory(mRule2->_opType) == data_type) // reg vs. (load memory) | |
0 | 3463 && (name_left != NULL) // NOT (load) |
3464 && (name_right == NULL) ) { // NOT (load memory foo) | |
3465 const Form *form2_left = name_left ? globals[name_left] : NULL; | |
3466 if( form2_left && form2_left->is_cisc_mem(globals) ) { | |
3467 cisc_spillable = Is_cisc_spillable; | |
3468 operand = _name; | |
3469 reg_type = _result; | |
3470 return Is_cisc_spillable; | |
3471 } else { | |
3472 cisc_spillable = Not_cisc_spillable; | |
3473 } | |
3474 } | |
3475 // Detect reg vs memory | |
3476 else if( form->is_cisc_reg(globals) && form2->is_cisc_mem(globals) ) { | |
3477 cisc_spillable = Is_cisc_spillable; | |
3478 operand = _name; | |
3479 reg_type = _result; | |
3480 return Is_cisc_spillable; | |
3481 } else { | |
3482 cisc_spillable = Not_cisc_spillable; | |
3483 } | |
3484 } | |
3485 | |
3486 // If cisc is still possible, check rest of tree | |
3487 if( cisc_spillable == Maybe_cisc_spillable ) { | |
3488 // Check that each has same number of operands at this level | |
3489 if( (_lChild && !(mRule2->_lChild)) || (_rChild && !(mRule2->_rChild)) ) return Not_cisc_spillable; | |
3490 | |
3491 // Check left operands | |
3492 if( (_lChild == NULL) && (mRule2->_lChild == NULL) ) { | |
3493 left_spillable = Maybe_cisc_spillable; | |
3494 } else { | |
3495 left_spillable = _lChild->cisc_spill_match(globals, registers, mRule2->_lChild, operand, reg_type); | |
3496 } | |
3497 | |
3498 // Check right operands | |
3499 if( (_rChild == NULL) && (mRule2->_rChild == NULL) ) { | |
3500 right_spillable = Maybe_cisc_spillable; | |
3501 } else { | |
3502 right_spillable = _rChild->cisc_spill_match(globals, registers, mRule2->_rChild, operand, reg_type); | |
3503 } | |
3504 | |
3505 // Combine results of left and right checks | |
3506 cisc_spillable = cisc_spill_merge(left_spillable, right_spillable); | |
3507 } | |
3508 | |
3509 return cisc_spillable; | |
3510 } | |
3511 | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3512 //---------------------------cisc_spill_match_rule------------------------------ |
0 | 3513 // Recursively check two MatchRules for legal conversion via cisc-spilling |
3514 // This method handles the root of Match tree, | |
3515 // general recursive checks done in MatchNode | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3516 int MatchRule::matchrule_cisc_spill_match(FormDict& globals, RegisterForm* registers, |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3517 MatchRule* mRule2, const char* &operand, |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3518 const char* ®_type) { |
0 | 3519 int cisc_spillable = Maybe_cisc_spillable; |
3520 int left_spillable = Maybe_cisc_spillable; | |
3521 int right_spillable = Maybe_cisc_spillable; | |
3522 | |
3523 // Check that each sets a result | |
3524 if( !(sets_result() && mRule2->sets_result()) ) return Not_cisc_spillable; | |
3525 // Check that each has same number of operands at this level | |
3526 if( (_lChild && !(mRule2->_lChild)) || (_rChild && !(mRule2->_rChild)) ) return Not_cisc_spillable; | |
3527 | |
3528 // Check left operands: at root, must be target of 'Set' | |
3529 if( (_lChild == NULL) || (mRule2->_lChild == NULL) ) { | |
3530 left_spillable = Not_cisc_spillable; | |
3531 } else { | |
3532 // Do not support cisc-spilling instruction's target location | |
3533 if( root_ops_match(globals, _lChild->_opType, mRule2->_lChild->_opType) ) { | |
3534 left_spillable = Maybe_cisc_spillable; | |
3535 } else { | |
3536 left_spillable = Not_cisc_spillable; | |
3537 } | |
3538 } | |
3539 | |
3540 // Check right operands: recursive walk to identify reg->mem operand | |
3541 if( (_rChild == NULL) && (mRule2->_rChild == NULL) ) { | |
3542 right_spillable = Maybe_cisc_spillable; | |
3543 } else { | |
3544 right_spillable = _rChild->cisc_spill_match(globals, registers, mRule2->_rChild, operand, reg_type); | |
3545 } | |
3546 | |
3547 // Combine results of left and right checks | |
3548 cisc_spillable = cisc_spill_merge(left_spillable, right_spillable); | |
3549 | |
3550 return cisc_spillable; | |
3551 } | |
3552 | |
3553 //----------------------------- equivalent ------------------------------------ | |
3554 // Recursively check to see if two match rules are equivalent. | |
3555 // This rule handles the root. | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3556 bool MatchRule::equivalent(FormDict &globals, MatchNode *mRule2) { |
0 | 3557 // Check that each sets a result |
3558 if (sets_result() != mRule2->sets_result()) { | |
3559 return false; | |
3560 } | |
3561 | |
3562 // Check that the current operands/operations match | |
3563 assert( _opType, "Must have _opType"); | |
3564 assert( mRule2->_opType, "Must have _opType"); | |
3565 const Form *form = globals[_opType]; | |
3566 const Form *form2 = globals[mRule2->_opType]; | |
3567 if( form != form2 ) { | |
3568 return false; | |
3569 } | |
3570 | |
3571 if (_lChild ) { | |
3572 if( !_lChild->equivalent(globals, mRule2->_lChild) ) | |
3573 return false; | |
3574 } else if (mRule2->_lChild) { | |
3575 return false; // I have NULL left child, mRule2 has non-NULL left child. | |
3576 } | |
3577 | |
3578 if (_rChild ) { | |
3579 if( !_rChild->equivalent(globals, mRule2->_rChild) ) | |
3580 return false; | |
3581 } else if (mRule2->_rChild) { | |
3582 return false; // I have NULL right child, mRule2 has non-NULL right child. | |
3583 } | |
3584 | |
3585 // We've made it through the gauntlet. | |
3586 return true; | |
3587 } | |
3588 | |
3589 //----------------------------- equivalent ------------------------------------ | |
3590 // Recursively check to see if two match rules are equivalent. | |
3591 // This rule handles the operands. | |
3592 bool MatchNode::equivalent(FormDict &globals, MatchNode *mNode2) { | |
3593 if( !mNode2 ) | |
3594 return false; | |
3595 | |
3596 // Check that the current operands/operations match | |
3597 assert( _opType, "Must have _opType"); | |
3598 assert( mNode2->_opType, "Must have _opType"); | |
3599 const Form *form = globals[_opType]; | |
3600 const Form *form2 = globals[mNode2->_opType]; | |
3601 return (form == form2); | |
3602 } | |
3603 | |
3604 //-------------------------- has_commutative_op ------------------------------- | |
3605 // Recursively check for commutative operations with subtree operands | |
3606 // which could be swapped. | |
3607 void MatchNode::count_commutative_op(int& count) { | |
3608 static const char *commut_op_list[] = { | |
3609 "AddI","AddL","AddF","AddD", | |
3610 "AndI","AndL", | |
3611 "MaxI","MinI", | |
3612 "MulI","MulL","MulF","MulD", | |
3613 "OrI" ,"OrL" , | |
3614 "XorI","XorL" | |
3615 }; | |
3616 int cnt = sizeof(commut_op_list)/sizeof(char*); | |
3617 | |
3618 if( _lChild && _rChild && (_lChild->_lChild || _rChild->_lChild) ) { | |
3619 // Don't swap if right operand is an immediate constant. | |
3620 bool is_const = false; | |
3621 if( _rChild->_lChild == NULL && _rChild->_rChild == NULL ) { | |
3622 FormDict &globals = _AD.globalNames(); | |
3623 const Form *form = globals[_rChild->_opType]; | |
3624 if ( form ) { | |
3625 OperandForm *oper = form->is_operand(); | |
3626 if( oper && oper->interface_type(globals) == Form::constant_interface ) | |
3627 is_const = true; | |
3628 } | |
3629 } | |
3630 if( !is_const ) { | |
3631 for( int i=0; i<cnt; i++ ) { | |
3632 if( strcmp(_opType, commut_op_list[i]) == 0 ) { | |
3633 count++; | |
3634 _commutative_id = count; // id should be > 0 | |
3635 break; | |
3636 } | |
3637 } | |
3638 } | |
3639 } | |
3640 if( _lChild ) | |
3641 _lChild->count_commutative_op(count); | |
3642 if( _rChild ) | |
3643 _rChild->count_commutative_op(count); | |
3644 } | |
3645 | |
3646 //-------------------------- swap_commutative_op ------------------------------ | |
3647 // Recursively swap specified commutative operation with subtree operands. | |
3648 void MatchNode::swap_commutative_op(bool atroot, int id) { | |
3649 if( _commutative_id == id ) { // id should be > 0 | |
3650 assert(_lChild && _rChild && (_lChild->_lChild || _rChild->_lChild ), | |
3651 "not swappable operation"); | |
3652 MatchNode* tmp = _lChild; | |
3653 _lChild = _rChild; | |
3654 _rChild = tmp; | |
3655 // Don't exit here since we need to build internalop. | |
3656 } | |
3657 | |
3658 bool is_set = ( strcmp(_opType, "Set") == 0 ); | |
3659 if( _lChild ) | |
3660 _lChild->swap_commutative_op(is_set, id); | |
3661 if( _rChild ) | |
3662 _rChild->swap_commutative_op(is_set, id); | |
3663 | |
3664 // If not the root, reduce this subtree to an internal operand | |
3665 if( !atroot && (_lChild || _rChild) ) { | |
3666 build_internalop(); | |
3667 } | |
3668 } | |
3669 | |
3670 //-------------------------- swap_commutative_op ------------------------------ | |
3671 // Recursively swap specified commutative operation with subtree operands. | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3672 void MatchRule::matchrule_swap_commutative_op(const char* instr_ident, int count, int& match_rules_cnt) { |
0 | 3673 assert(match_rules_cnt < 100," too many match rule clones"); |
3674 // Clone | |
3675 MatchRule* clone = new MatchRule(_AD, this); | |
3676 // Swap operands of commutative operation | |
3677 ((MatchNode*)clone)->swap_commutative_op(true, count); | |
3678 char* buf = (char*) malloc(strlen(instr_ident) + 4); | |
3679 sprintf(buf, "%s_%d", instr_ident, match_rules_cnt++); | |
3680 clone->_result = buf; | |
3681 | |
3682 clone->_next = this->_next; | |
3683 this-> _next = clone; | |
3684 if( (--count) > 0 ) { | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3685 this-> matchrule_swap_commutative_op(instr_ident, count, match_rules_cnt); |
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3686 clone->matchrule_swap_commutative_op(instr_ident, count, match_rules_cnt); |
0 | 3687 } |
3688 } | |
3689 | |
3690 //------------------------------MatchRule-------------------------------------- | |
3691 MatchRule::MatchRule(ArchDesc &ad) | |
3692 : MatchNode(ad), _depth(0), _construct(NULL), _numchilds(0) { | |
3693 _next = NULL; | |
3694 } | |
3695 | |
3696 MatchRule::MatchRule(ArchDesc &ad, MatchRule* mRule) | |
3697 : MatchNode(ad, *mRule, 0), _depth(mRule->_depth), | |
3698 _construct(mRule->_construct), _numchilds(mRule->_numchilds) { | |
3699 _next = NULL; | |
3700 } | |
3701 | |
3702 MatchRule::MatchRule(ArchDesc &ad, MatchNode* mroot, int depth, char *cnstr, | |
3703 int numleaves) | |
3704 : MatchNode(ad,*mroot), _depth(depth), _construct(cnstr), | |
3705 _numchilds(0) { | |
3706 _next = NULL; | |
3707 mroot->_lChild = NULL; | |
3708 mroot->_rChild = NULL; | |
3709 delete mroot; | |
3710 _numleaves = numleaves; | |
3711 _numchilds = (_lChild ? 1 : 0) + (_rChild ? 1 : 0); | |
3712 } | |
3713 MatchRule::~MatchRule() { | |
3714 } | |
3715 | |
3716 // Recursive call collecting info on top-level operands, not transitive. | |
3717 // Implementation does not modify state of internal structures. | |
603
dbbe28fc66b5
6778669: Patch from Red Hat -- fixes compilation errors
twisti
parents:
602
diff
changeset
|
3718 void MatchRule::append_components(FormDict& locals, ComponentList& components, bool def_flag) const { |
0 | 3719 assert (_name != NULL, "MatchNode::build_components encountered empty node\n"); |
3720 | |
3721 MatchNode::append_components(locals, components, | |
3722 false /* not necessarily a def */); | |
3723 } | |
3724 | |
3725 // Recursive call on all operands' match rules in my match rule. | |
3726 // Implementation does not modify state of internal structures since they | |
3727 // can be shared. | |
3728 // The MatchNode that is called first treats its | |
3729 bool MatchRule::base_operand(uint &position0, FormDict &globals, | |
3730 const char *&result, const char * &name, | |
3731 const char * &opType)const{ | |
3732 uint position = position0; | |
3733 | |
3734 return (MatchNode::base_operand( position, globals, result, name, opType)); | |
3735 } | |
3736 | |
3737 | |
3738 bool MatchRule::is_base_register(FormDict &globals) const { | |
3739 uint position = 1; | |
3740 const char *result = NULL; | |
3741 const char *name = NULL; | |
3742 const char *opType = NULL; | |
3743 if (!base_operand(position, globals, result, name, opType)) { | |
3744 position = 0; | |
3745 if( base_operand(position, globals, result, name, opType) && | |
3746 (strcmp(opType,"RegI")==0 || | |
3747 strcmp(opType,"RegP")==0 || | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
3748 strcmp(opType,"RegN")==0 || |
0 | 3749 strcmp(opType,"RegL")==0 || |
3750 strcmp(opType,"RegF")==0 || | |
3751 strcmp(opType,"RegD")==0 || | |
3752 strcmp(opType,"Reg" )==0) ) { | |
3753 return 1; | |
3754 } | |
3755 } | |
3756 return 0; | |
3757 } | |
3758 | |
3759 Form::DataType MatchRule::is_base_constant(FormDict &globals) const { | |
3760 uint position = 1; | |
3761 const char *result = NULL; | |
3762 const char *name = NULL; | |
3763 const char *opType = NULL; | |
3764 if (!base_operand(position, globals, result, name, opType)) { | |
3765 position = 0; | |
3766 if (base_operand(position, globals, result, name, opType)) { | |
3767 return ideal_to_const_type(opType); | |
3768 } | |
3769 } | |
3770 return Form::none; | |
3771 } | |
3772 | |
3773 bool MatchRule::is_chain_rule(FormDict &globals) const { | |
3774 | |
3775 // Check for chain rule, and do not generate a match list for it | |
3776 if ((_lChild == NULL) && (_rChild == NULL) ) { | |
3777 const Form *form = globals[_opType]; | |
3778 // If this is ideal, then it is a base match, not a chain rule. | |
3779 if ( form && form->is_operand() && (!form->ideal_only())) { | |
3780 return true; | |
3781 } | |
3782 } | |
3783 // Check for "Set" form of chain rule, and do not generate a match list | |
3784 if (_rChild) { | |
3785 const char *rch = _rChild->_opType; | |
3786 const Form *form = globals[rch]; | |
3787 if ((!strcmp(_opType,"Set") && | |
3788 ((form) && form->is_operand()))) { | |
3789 return true; | |
3790 } | |
3791 } | |
3792 return false; | |
3793 } | |
3794 | |
3795 int MatchRule::is_ideal_copy() const { | |
3796 if( _rChild ) { | |
3797 const char *opType = _rChild->_opType; | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3798 #if 1 |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3799 if( strcmp(opType,"CastIP")==0 ) |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3800 return 1; |
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3801 #else |
0 | 3802 if( strcmp(opType,"CastII")==0 ) |
3803 return 1; | |
3804 // Do not treat *CastPP this way, because it | |
3805 // may transfer a raw pointer to an oop. | |
3806 // If the register allocator were to coalesce this | |
3807 // into a single LRG, the GC maps would be incorrect. | |
3808 //if( strcmp(opType,"CastPP")==0 ) | |
3809 // return 1; | |
3810 //if( strcmp(opType,"CheckCastPP")==0 ) | |
3811 // return 1; | |
3812 // | |
3813 // Do not treat CastX2P or CastP2X this way, because | |
3814 // raw pointers and int types are treated differently | |
3815 // when saving local & stack info for safepoints in | |
3816 // Output(). | |
3817 //if( strcmp(opType,"CastX2P")==0 ) | |
3818 // return 1; | |
3819 //if( strcmp(opType,"CastP2X")==0 ) | |
3820 // return 1; | |
342
37f87013dfd8
6711316: Open source the Garbage-First garbage collector
ysr
parents:
113
diff
changeset
|
3821 #endif |
0 | 3822 } |
3823 if( is_chain_rule(_AD.globalNames()) && | |
3824 _lChild && strncmp(_lChild->_opType,"stackSlot",9)==0 ) | |
3825 return 1; | |
3826 return 0; | |
3827 } | |
3828 | |
3829 | |
3830 int MatchRule::is_expensive() const { | |
3831 if( _rChild ) { | |
3832 const char *opType = _rChild->_opType; | |
3833 if( strcmp(opType,"AtanD")==0 || | |
3834 strcmp(opType,"CosD")==0 || | |
3835 strcmp(opType,"DivD")==0 || | |
3836 strcmp(opType,"DivF")==0 || | |
3837 strcmp(opType,"DivI")==0 || | |
3838 strcmp(opType,"ExpD")==0 || | |
3839 strcmp(opType,"LogD")==0 || | |
3840 strcmp(opType,"Log10D")==0 || | |
3841 strcmp(opType,"ModD")==0 || | |
3842 strcmp(opType,"ModF")==0 || | |
3843 strcmp(opType,"ModI")==0 || | |
3844 strcmp(opType,"PowD")==0 || | |
3845 strcmp(opType,"SinD")==0 || | |
3846 strcmp(opType,"SqrtD")==0 || | |
3847 strcmp(opType,"TanD")==0 || | |
3848 strcmp(opType,"ConvD2F")==0 || | |
3849 strcmp(opType,"ConvD2I")==0 || | |
3850 strcmp(opType,"ConvD2L")==0 || | |
3851 strcmp(opType,"ConvF2D")==0 || | |
3852 strcmp(opType,"ConvF2I")==0 || | |
3853 strcmp(opType,"ConvF2L")==0 || | |
3854 strcmp(opType,"ConvI2D")==0 || | |
3855 strcmp(opType,"ConvI2F")==0 || | |
3856 strcmp(opType,"ConvI2L")==0 || | |
3857 strcmp(opType,"ConvL2D")==0 || | |
3858 strcmp(opType,"ConvL2F")==0 || | |
3859 strcmp(opType,"ConvL2I")==0 || | |
247 | 3860 strcmp(opType,"DecodeN")==0 || |
3861 strcmp(opType,"EncodeP")==0 || | |
0 | 3862 strcmp(opType,"RoundDouble")==0 || |
3863 strcmp(opType,"RoundFloat")==0 || | |
3864 strcmp(opType,"ReverseBytesI")==0 || | |
3865 strcmp(opType,"ReverseBytesL")==0 || | |
1396
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
986
diff
changeset
|
3866 strcmp(opType,"ReverseBytesUS")==0 || |
d7f654633cfe
6946040: add intrinsic for short and char reverseBytes
never
parents:
986
diff
changeset
|
3867 strcmp(opType,"ReverseBytesS")==0 || |
0 | 3868 strcmp(opType,"Replicate16B")==0 || |
3869 strcmp(opType,"Replicate8B")==0 || | |
3870 strcmp(opType,"Replicate4B")==0 || | |
3871 strcmp(opType,"Replicate8C")==0 || | |
3872 strcmp(opType,"Replicate4C")==0 || | |
3873 strcmp(opType,"Replicate8S")==0 || | |
3874 strcmp(opType,"Replicate4S")==0 || | |
3875 strcmp(opType,"Replicate4I")==0 || | |
3876 strcmp(opType,"Replicate2I")==0 || | |
3877 strcmp(opType,"Replicate2L")==0 || | |
3878 strcmp(opType,"Replicate4F")==0 || | |
3879 strcmp(opType,"Replicate2F")==0 || | |
3880 strcmp(opType,"Replicate2D")==0 || | |
3881 0 /* 0 to line up columns nicely */ ) | |
3882 return 1; | |
3883 } | |
3884 return 0; | |
3885 } | |
3886 | |
3887 bool MatchRule::is_ideal_unlock() const { | |
3888 if( !_opType ) return false; | |
3889 return !strcmp(_opType,"Unlock") || !strcmp(_opType,"FastUnlock"); | |
3890 } | |
3891 | |
3892 | |
3893 bool MatchRule::is_ideal_call_leaf() const { | |
3894 if( !_opType ) return false; | |
3895 return !strcmp(_opType,"CallLeaf") || | |
3896 !strcmp(_opType,"CallLeafNoFP"); | |
3897 } | |
3898 | |
3899 | |
3900 bool MatchRule::is_ideal_if() const { | |
3901 if( !_opType ) return false; | |
3902 return | |
3903 !strcmp(_opType,"If" ) || | |
3904 !strcmp(_opType,"CountedLoopEnd"); | |
3905 } | |
3906 | |
3907 bool MatchRule::is_ideal_fastlock() const { | |
3908 if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) { | |
3909 return (strcmp(_rChild->_opType,"FastLock") == 0); | |
3910 } | |
3911 return false; | |
3912 } | |
3913 | |
3914 bool MatchRule::is_ideal_membar() const { | |
3915 if( !_opType ) return false; | |
3916 return | |
3917 !strcmp(_opType,"MemBarAcquire" ) || | |
3918 !strcmp(_opType,"MemBarRelease" ) || | |
3919 !strcmp(_opType,"MemBarVolatile" ) || | |
3920 !strcmp(_opType,"MemBarCPUOrder" ) ; | |
3921 } | |
3922 | |
3923 bool MatchRule::is_ideal_loadPC() const { | |
3924 if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) { | |
3925 return (strcmp(_rChild->_opType,"LoadPC") == 0); | |
3926 } | |
3927 return false; | |
3928 } | |
3929 | |
3930 bool MatchRule::is_ideal_box() const { | |
3931 if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) { | |
3932 return (strcmp(_rChild->_opType,"Box") == 0); | |
3933 } | |
3934 return false; | |
3935 } | |
3936 | |
3937 bool MatchRule::is_ideal_goto() const { | |
3938 bool ideal_goto = false; | |
3939 | |
3940 if( _opType && (strcmp(_opType,"Goto") == 0) ) { | |
3941 ideal_goto = true; | |
3942 } | |
3943 return ideal_goto; | |
3944 } | |
3945 | |
3946 bool MatchRule::is_ideal_jump() const { | |
3947 if( _opType ) { | |
3948 if( !strcmp(_opType,"Jump") ) | |
3949 return true; | |
3950 } | |
3951 return false; | |
3952 } | |
3953 | |
3954 bool MatchRule::is_ideal_bool() const { | |
3955 if( _opType ) { | |
3956 if( !strcmp(_opType,"Bool") ) | |
3957 return true; | |
3958 } | |
3959 return false; | |
3960 } | |
3961 | |
3962 | |
3963 Form::DataType MatchRule::is_ideal_load() const { | |
3964 Form::DataType ideal_load = Form::none; | |
3965 | |
3966 if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) { | |
3967 const char *opType = _rChild->_opType; | |
3968 ideal_load = is_load_from_memory(opType); | |
3969 } | |
3970 | |
3971 return ideal_load; | |
3972 } | |
3973 | |
3974 | |
855
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3975 bool MatchRule::skip_antidep_check() const { |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3976 // Some loads operate on what is effectively immutable memory so we |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3977 // should skip the anti dep computations. For some of these nodes |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3978 // the rewritable field keeps the anti dep logic from triggering but |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3979 // for certain kinds of LoadKlass it does not since they are |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3980 // actually reading memory which could be rewritten by the runtime, |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3981 // though never by generated code. This disables it uniformly for |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3982 // the nodes that behave like this: LoadKlass, LoadNKlass and |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3983 // LoadRange. |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3984 if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) { |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3985 const char *opType = _rChild->_opType; |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3986 if (strcmp("LoadKlass", opType) == 0 || |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3987 strcmp("LoadNKlass", opType) == 0 || |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3988 strcmp("LoadRange", opType) == 0) { |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3989 return true; |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3990 } |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3991 } |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3992 |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3993 return false; |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3994 } |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3995 |
f9094a5e1c8a
6857159: local schedule failed with checkcast of Thread.currentThread()
never
parents:
681
diff
changeset
|
3996 |
0 | 3997 Form::DataType MatchRule::is_ideal_store() const { |
3998 Form::DataType ideal_store = Form::none; | |
3999 | |
4000 if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) { | |
4001 const char *opType = _rChild->_opType; | |
4002 ideal_store = is_store_to_memory(opType); | |
4003 } | |
4004 | |
4005 return ideal_store; | |
4006 } | |
4007 | |
4008 | |
4009 void MatchRule::dump() { | |
4010 output(stderr); | |
4011 } | |
4012 | |
4013 void MatchRule::output(FILE *fp) { | |
4014 fprintf(fp,"MatchRule: ( %s",_name); | |
4015 if (_lChild) _lChild->output(fp); | |
4016 if (_rChild) _rChild->output(fp); | |
4017 fprintf(fp," )\n"); | |
4018 fprintf(fp," nesting depth = %d\n", _depth); | |
4019 if (_result) fprintf(fp," Result Type = %s", _result); | |
4020 fprintf(fp,"\n"); | |
4021 } | |
4022 | |
4023 //------------------------------Attribute-------------------------------------- | |
4024 Attribute::Attribute(char *id, char* val, int type) | |
4025 : _ident(id), _val(val), _atype(type) { | |
4026 } | |
4027 Attribute::~Attribute() { | |
4028 } | |
4029 | |
4030 int Attribute::int_val(ArchDesc &ad) { | |
4031 // Make sure it is an integer constant: | |
4032 int result = 0; | |
4033 if (!_val || !ADLParser::is_int_token(_val, result)) { | |
4034 ad.syntax_err(0, "Attribute %s must have an integer value: %s", | |
4035 _ident, _val ? _val : ""); | |
4036 } | |
4037 return result; | |
4038 } | |
4039 | |
4040 void Attribute::dump() { | |
4041 output(stderr); | |
4042 } // Debug printer | |
4043 | |
4044 // Write to output files | |
4045 void Attribute::output(FILE *fp) { | |
4046 fprintf(fp,"Attribute: %s %s\n", (_ident?_ident:""), (_val?_val:"")); | |
4047 } | |
4048 | |
4049 //------------------------------FormatRule---------------------------------- | |
4050 FormatRule::FormatRule(char *temp) | |
4051 : _temp(temp) { | |
4052 } | |
4053 FormatRule::~FormatRule() { | |
4054 } | |
4055 | |
4056 void FormatRule::dump() { | |
4057 output(stderr); | |
4058 } | |
4059 | |
4060 // Write to output files | |
4061 void FormatRule::output(FILE *fp) { | |
4062 fprintf(fp,"\nFormat Rule: \n%s", (_temp?_temp:"")); | |
4063 fprintf(fp,"\n"); | |
4064 } |