|
1 /* |
|
2 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. |
|
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 * |
|
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or |
|
21 * have any questions. |
|
22 * |
|
23 */ |
|
24 |
|
25 // FORMSOPT.HPP - ADL Parser Target Specific Optimization Forms Classes |
|
26 |
|
27 // Class List |
|
28 class Form; |
|
29 class InstructForm; |
|
30 class OperandForm; |
|
31 class OpClassForm; |
|
32 class AttributeForm; |
|
33 class RegisterForm; |
|
34 class PipelineForm; |
|
35 class SourceForm; |
|
36 class EncodeForm; |
|
37 class Component; |
|
38 class Constraint; |
|
39 class Predicate; |
|
40 class MatchRule; |
|
41 class Attribute; |
|
42 class Effect; |
|
43 class ExpandRule; |
|
44 class RewriteRule; |
|
45 class ConstructRule; |
|
46 class FormatRule; |
|
47 class Peephole; |
|
48 class PeepMatch; |
|
49 class PeepConstraint; |
|
50 class EncClass; |
|
51 class Interface; |
|
52 class RegInterface; |
|
53 class ConstInterface; |
|
54 class MemInterface; |
|
55 class CondInterface; |
|
56 class Opcode; |
|
57 class InsEncode; |
|
58 class RegDef; |
|
59 class RegClass; |
|
60 class AllocClass; |
|
61 class ResourceForm; |
|
62 class PipeClassForm; |
|
63 class PipeClassOperandForm; |
|
64 class PipeClassResourceForm; |
|
65 class PeepMatch; |
|
66 class PeepConstraint; |
|
67 class PeepReplace; |
|
68 class MatchList; |
|
69 |
|
70 class ArchDesc; |
|
71 |
|
72 //==============================Register Allocation============================ |
|
73 //------------------------------RegisterForm----------------------------------- |
|
74 class RegisterForm : public Form { |
|
75 private: |
|
76 AllocClass *_current_ac; // State used by iter_RegDefs() |
|
77 |
|
78 public: |
|
79 // Public Data |
|
80 NameList _rdefs; // List of register definition names |
|
81 Dict _regDef; // map register name to RegDef* |
|
82 |
|
83 NameList _rclasses; // List of register class names |
|
84 Dict _regClass; // map register class name to RegClass* |
|
85 |
|
86 NameList _aclasses; // List of allocation class names |
|
87 Dict _allocClass; // Dictionary of allocation classes |
|
88 |
|
89 static int _reg_ctr; // Register counter |
|
90 static int RegMask_Size(); // Compute RegMask size |
|
91 |
|
92 // Public Methods |
|
93 RegisterForm(); |
|
94 ~RegisterForm(); |
|
95 |
|
96 void addRegDef(char *regName, char *callingConv, char *c_conv, |
|
97 char * idealtype, char *encoding, char* concreteName); |
|
98 RegClass *addRegClass(const char *className); |
|
99 AllocClass *addAllocClass(char *allocName); |
|
100 void addSpillRegClass(); |
|
101 |
|
102 // Provide iteration over all register definitions |
|
103 // in the order used by the register allocator |
|
104 void reset_RegDefs(); |
|
105 RegDef *iter_RegDefs(); |
|
106 RegDef *getRegDef (const char *regName); |
|
107 |
|
108 RegClass *getRegClass(const char *className); |
|
109 |
|
110 // Return register mask, compressed chunk and register # |
|
111 uint reg_mask(char *register_class); |
|
112 |
|
113 // Check that register classes are compatible with chunks |
|
114 bool verify(); |
|
115 |
|
116 void dump(); // Debug printer |
|
117 void output(FILE *fp); // Write info to output files |
|
118 }; |
|
119 |
|
120 //------------------------------RegDef----------------------------------------- |
|
121 class RegDef : public Form { |
|
122 public: |
|
123 // Public Data |
|
124 const char *_regname; // ADLC (Opto) Register name |
|
125 const char *_callconv; // Calling convention |
|
126 const char *_c_conv; // Native calling convention, 'C' |
|
127 const char *_idealtype; // Ideal Type for register save/restore |
|
128 const char *_concrete; // concrete register name |
|
129 |
|
130 private: |
|
131 const char *_register_encode; // The register encoding |
|
132 // The chunk and register mask bits define info for register allocation |
|
133 uint32 _register_num; // Which register am I |
|
134 |
|
135 public: |
|
136 // Public Methods |
|
137 RegDef(char *regname, char *callconv, char *c_conv, |
|
138 char *idealtype, char *encoding, char *concrete); |
|
139 ~RegDef(); // Destructor |
|
140 |
|
141 // Interface to define/redefine the register number |
|
142 void set_register_num(uint32 new_register_num); |
|
143 |
|
144 // Bit pattern used for generating machine code |
|
145 const char *register_encode() const; |
|
146 // Register number used in machine-independent code |
|
147 uint32 register_num() const; |
|
148 |
|
149 void dump(); // Debug printer |
|
150 void output(FILE *fp); // Write info to output files |
|
151 }; |
|
152 |
|
153 //------------------------------RegClass--------------------------------------- |
|
154 class RegClass : public Form { |
|
155 public: |
|
156 // Public Data |
|
157 const char *_classid; // Name of class |
|
158 NameList _regDefs; // List of registers in class |
|
159 Dict _regDef; // Dictionary of registers in class |
|
160 bool _stack_or_reg; // Allowed on any stack slot |
|
161 |
|
162 // Public Methods |
|
163 RegClass(const char *classid);// Constructor |
|
164 |
|
165 void addReg(RegDef *regDef); // Add a register to this class |
|
166 |
|
167 uint size() const; // Number of registers in class |
|
168 int regs_in_word( int wordnum, bool stack_also ); |
|
169 |
|
170 const RegDef *get_RegDef(const char *regDef_name) const; |
|
171 |
|
172 // Returns the lowest numbered register in the mask. |
|
173 const RegDef* find_first_elem(); |
|
174 |
|
175 // Iteration support |
|
176 void reset(); // Reset the following two iterators |
|
177 RegDef *RegDef_iter(); // which move jointly, |
|
178 const char *rd_name_iter(); // invoking either advances both. |
|
179 |
|
180 void dump(); // Debug printer |
|
181 void output(FILE *fp); // Write info to output files |
|
182 }; |
|
183 |
|
184 //------------------------------AllocClass------------------------------------- |
|
185 class AllocClass : public Form { |
|
186 private: |
|
187 |
|
188 public: |
|
189 // Public Data |
|
190 char *_classid; // Name of class |
|
191 NameList _regDefs; // List of registers in class |
|
192 Dict _regDef; // Dictionary of registers in class |
|
193 |
|
194 // Public Methods |
|
195 AllocClass(char *classid); // Constructor |
|
196 |
|
197 void addReg(RegDef *regDef); // Add a register to this class |
|
198 uint size() {return _regDef.Size();} // Number of registers in class |
|
199 |
|
200 void dump(); // Debug printer |
|
201 void output(FILE *fp); // Write info to output files |
|
202 }; |
|
203 |
|
204 |
|
205 //==============================Frame Handling================================ |
|
206 //------------------------------FrameForm------------------------------------- |
|
207 class FrameForm : public Form { |
|
208 private: |
|
209 |
|
210 public: |
|
211 // Public Data |
|
212 bool _direction; // Direction of stack growth |
|
213 char *_sync_stack_slots; |
|
214 char *_inline_cache_reg; |
|
215 char *_interpreter_method_oop_reg; |
|
216 char *_interpreter_frame_pointer_reg; |
|
217 char *_cisc_spilling_operand_name; |
|
218 char *_frame_pointer; |
|
219 char *_c_frame_pointer; |
|
220 char *_alignment; |
|
221 bool _return_addr_loc; |
|
222 bool _c_return_addr_loc; |
|
223 char *_return_addr; |
|
224 char *_c_return_addr; |
|
225 char *_in_preserve_slots; |
|
226 char *_varargs_C_out_slots_killed; |
|
227 char *_calling_convention; |
|
228 char *_c_calling_convention; |
|
229 char *_return_value; |
|
230 char *_c_return_value; |
|
231 |
|
232 // Public Methods |
|
233 FrameForm(); |
|
234 ~FrameForm(); |
|
235 |
|
236 void dump(); // Debug printer |
|
237 void output(FILE *fp); // Write info to output files |
|
238 }; |
|
239 |
|
240 |
|
241 //==============================Scheduling===================================== |
|
242 //------------------------------PipelineForm----------------------------------- |
|
243 class PipelineForm : public Form { |
|
244 private: |
|
245 |
|
246 public: |
|
247 // Public Data |
|
248 NameList _reslist; // List of pipeline resources |
|
249 FormDict _resdict; // Resource Name -> ResourceForm mapping |
|
250 int _rescount; // Number of resources (ignores OR cases) |
|
251 int _maxcycleused; // Largest cycle used relative to beginning of instruction |
|
252 |
|
253 NameList _stages; // List of pipeline stages on architecture |
|
254 int _stagecnt; // Number of stages listed |
|
255 |
|
256 NameList _classlist; // List of pipeline classes |
|
257 FormDict _classdict; // Class Name -> PipeClassForm mapping |
|
258 int _classcnt; // Number of classes |
|
259 |
|
260 NameList _noplist; // List of NOP instructions |
|
261 int _nopcnt; // Number of nop instructions |
|
262 |
|
263 bool _variableSizeInstrs; // Indicates if this architecture has variable sized instructions |
|
264 bool _branchHasDelaySlot; // Indicates that branches have delay slot instructions |
|
265 int _maxInstrsPerBundle; // Indicates the maximum number of instructions for ILP |
|
266 int _maxBundlesPerCycle; // Indicates the maximum number of bundles for ILP |
|
267 int _instrUnitSize; // The minimum instruction unit size, in bytes |
|
268 int _bundleUnitSize; // The bundle unit size, in bytes |
|
269 int _instrFetchUnitSize; // The size of the I-fetch unit, in bytes [must be power of 2] |
|
270 int _instrFetchUnits; // The number of I-fetch units processed per cycle |
|
271 |
|
272 // Public Methods |
|
273 PipelineForm(); |
|
274 ~PipelineForm(); |
|
275 |
|
276 void dump(); // Debug printer |
|
277 void output(FILE *fp); // Write info to output files |
|
278 }; |
|
279 |
|
280 //------------------------------ResourceForm----------------------------------- |
|
281 class ResourceForm : public Form { |
|
282 public: |
|
283 unsigned mask() const { return _resmask; }; |
|
284 |
|
285 private: |
|
286 // Public Data |
|
287 unsigned _resmask; // Resource Mask (OR of resource specifier bits) |
|
288 |
|
289 public: |
|
290 |
|
291 // Virtual Methods |
|
292 virtual ResourceForm *is_resource() const; |
|
293 |
|
294 // Public Methods |
|
295 ResourceForm(unsigned resmask); // Constructor |
|
296 ~ResourceForm(); // Destructor |
|
297 |
|
298 void dump(); // Debug printer |
|
299 void output(FILE *fp); // Write info to output files |
|
300 }; |
|
301 |
|
302 //------------------------------PipeClassOperandForm----------------------------- |
|
303 class PipeClassOperandForm : public Form { |
|
304 private: |
|
305 |
|
306 public: |
|
307 // Public Data |
|
308 const char *_stage; // Name of Stage |
|
309 unsigned _iswrite; // Read or Write |
|
310 unsigned _more_instrs; // Additional Instructions |
|
311 |
|
312 // Public Methods |
|
313 PipeClassOperandForm(const char *stage, unsigned iswrite, unsigned more_instrs) |
|
314 : _stage(stage) |
|
315 , _iswrite(iswrite) |
|
316 , _more_instrs(more_instrs) |
|
317 {}; |
|
318 |
|
319 ~PipeClassOperandForm() {}; // Destructor |
|
320 |
|
321 bool isWrite() const { return _iswrite != 0; } |
|
322 |
|
323 void dump(); // Debug printer |
|
324 void output(FILE *fp); // Write info to output files |
|
325 }; |
|
326 |
|
327 //------------------------------PipeClassResourceForm-------------------------- |
|
328 class PipeClassResourceForm : public Form { |
|
329 private: |
|
330 |
|
331 public: |
|
332 // Public Data |
|
333 const char *_resource; // Resource |
|
334 const char *_stage; // Stage the resource is used in |
|
335 int _cycles; // Number of cycles the resource is used |
|
336 |
|
337 // Public Methods |
|
338 PipeClassResourceForm(const char *resource, const char *stage, int cycles) |
|
339 // Constructor |
|
340 : _resource(resource) |
|
341 , _stage(stage) |
|
342 , _cycles(cycles) |
|
343 {}; |
|
344 |
|
345 ~PipeClassResourceForm() {}; // Destructor |
|
346 |
|
347 void dump(); // Debug printer |
|
348 void output(FILE *fp); // Write info to output files |
|
349 }; |
|
350 |
|
351 //------------------------------PipeClassForm---------------------------------- |
|
352 class PipeClassForm : public Form { |
|
353 private: |
|
354 |
|
355 public: |
|
356 |
|
357 // Public Data |
|
358 const char *_ident; // Name of class |
|
359 int _num; // Used in name of MachNode subclass |
|
360 NameList _parameters; // Locally defined names |
|
361 FormDict _localNames; // Table of operands & their types |
|
362 FormDict _localUsage; // Table of operand usage |
|
363 FormList _resUsage; // List of resource usage |
|
364 NameList _instructs; // List of instructions and machine nodes that use this pipeline class |
|
365 bool _has_fixed_latency; // Always takes this number of cycles |
|
366 int _fixed_latency; // Always takes this number of cycles |
|
367 int _instruction_count; // Number of instructions in first bundle |
|
368 bool _has_multiple_bundles; // Indicates if 1 or multiple bundles |
|
369 bool _has_branch_delay_slot; // Has branch delay slot as last instruction |
|
370 bool _force_serialization; // This node serializes relative to surrounding nodes |
|
371 bool _may_have_no_code; // This node may generate no code based on register allocation |
|
372 |
|
373 // Virtual Methods |
|
374 virtual PipeClassForm *is_pipeclass() const; |
|
375 |
|
376 // Public Methods |
|
377 PipeClassForm(const char *id, int num); |
|
378 // Constructor |
|
379 ~PipeClassForm(); // Destructor |
|
380 |
|
381 bool hasFixedLatency() { return _has_fixed_latency; } |
|
382 int fixedLatency() { return _fixed_latency; } |
|
383 |
|
384 void setFixedLatency(int fixed_latency) { _has_fixed_latency = 1; _fixed_latency = fixed_latency; } |
|
385 |
|
386 void setInstructionCount(int i) { _instruction_count = i; } |
|
387 void setMultipleBundles(bool b) { _has_multiple_bundles = b; } |
|
388 void setBranchDelay(bool s) { _has_branch_delay_slot = s; } |
|
389 void setForceSerialization(bool s) { _force_serialization = s; } |
|
390 void setMayHaveNoCode(bool s) { _may_have_no_code = s; } |
|
391 |
|
392 int InstructionCount() const { return _instruction_count; } |
|
393 bool hasMultipleBundles() const { return _has_multiple_bundles; } |
|
394 bool hasBranchDelay() const { return _has_branch_delay_slot; } |
|
395 bool forceSerialization() const { return _force_serialization; } |
|
396 bool mayHaveNoCode() const { return _may_have_no_code; } |
|
397 |
|
398 void dump(); // Debug printer |
|
399 void output(FILE *fp); // Write info to output files |
|
400 }; |
|
401 |
|
402 |
|
403 //==============================Peephole Optimization========================== |
|
404 //------------------------------Peephole--------------------------------------- |
|
405 class Peephole : public Form { |
|
406 private: |
|
407 static int _peephole_counter;// Incremented by each peephole rule parsed |
|
408 int _peephole_number;// Remember my order in architecture description |
|
409 PeepMatch *_match; // Instruction pattern to match |
|
410 PeepConstraint *_constraint; // List of additional constraints |
|
411 PeepReplace *_replace; // Instruction pattern to substitute in |
|
412 |
|
413 Peephole *_next; |
|
414 |
|
415 public: |
|
416 // Public Methods |
|
417 Peephole(); |
|
418 ~Peephole(); |
|
419 |
|
420 // Append a peephole rule with the same root instruction |
|
421 void append_peephole(Peephole *next_peephole); |
|
422 |
|
423 // Store the components of this peephole rule |
|
424 void add_match(PeepMatch *only_one_match); |
|
425 void append_constraint(PeepConstraint *next_constraint); |
|
426 void add_replace(PeepReplace *only_one_replacement); |
|
427 |
|
428 // Access the components of this peephole rule |
|
429 int peephole_number() { return _peephole_number; } |
|
430 PeepMatch *match() { return _match; } |
|
431 PeepConstraint *constraints() { return _constraint; } |
|
432 PeepReplace *replacement() { return _replace; } |
|
433 Peephole *next() { return _next; } |
|
434 |
|
435 void dump(); // Debug printer |
|
436 void output(FILE *fp); // Write info to output files |
|
437 }; |
|
438 |
|
439 |
|
440 class PeepMatch : public Form { |
|
441 private: |
|
442 char *_rule; |
|
443 // NameList _depth; // Depth of this instruction |
|
444 NameList _parent; |
|
445 NameList _position; |
|
446 NameList _instrs; // List of instructions in match rule |
|
447 NameList _input; // input position in parent's instruction |
|
448 int _max_position; |
|
449 |
|
450 public: |
|
451 // Public Methods |
|
452 PeepMatch(char *rule); |
|
453 ~PeepMatch(); |
|
454 |
|
455 // Insert info into the match-rule |
|
456 void add_instruction(int parent, int position, const char *name, int input); |
|
457 |
|
458 // Access info about instructions in the peep-match rule |
|
459 int max_position(); |
|
460 const char *instruction_name(intptr_t position); |
|
461 // Iterate through all info on matched instructions |
|
462 void reset(); |
|
463 void next_instruction( intptr_t &parent, intptr_t &position, const char * &name, intptr_t &input ); |
|
464 // 'true' if current position in iteration is a placeholder, not matched. |
|
465 bool is_placeholder(); |
|
466 |
|
467 void dump(); |
|
468 void output(FILE *fp); |
|
469 }; |
|
470 |
|
471 |
|
472 class PeepConstraint : public Form { |
|
473 private: |
|
474 PeepConstraint *_next; // Additional constraints ANDed together |
|
475 |
|
476 public: |
|
477 const intptr_t _left_inst; |
|
478 const char *_left_op; |
|
479 const char *_relation; |
|
480 const intptr_t _right_inst; |
|
481 const char *_right_op; |
|
482 |
|
483 public: |
|
484 // Public Methods |
|
485 PeepConstraint(intptr_t left_inst, char *left_op, char *relation, |
|
486 intptr_t right_inst, char *right_op); |
|
487 ~PeepConstraint(); |
|
488 |
|
489 // Check if constraints use instruction at position |
|
490 bool constrains_instruction(intptr_t position); |
|
491 |
|
492 // Add another constraint |
|
493 void append(PeepConstraint *next_peep_constraint); |
|
494 // Access the next constraint in the list |
|
495 PeepConstraint *next(); |
|
496 |
|
497 void dump(); |
|
498 void output(FILE *fp); |
|
499 }; |
|
500 |
|
501 |
|
502 class PeepReplace : public Form { |
|
503 private: |
|
504 char *_rule; |
|
505 NameList _instruction; |
|
506 NameList _operand_inst_num; |
|
507 NameList _operand_op_name; |
|
508 |
|
509 public: |
|
510 |
|
511 // Public Methods |
|
512 PeepReplace(char *rule); |
|
513 ~PeepReplace(); |
|
514 |
|
515 // Add contents of peepreplace |
|
516 void add_instruction(char *root); |
|
517 void add_operand( int inst_num, char *inst_operand ); |
|
518 |
|
519 // Access contents of peepreplace |
|
520 void reset(); |
|
521 void next_instruction(const char * &root); |
|
522 void next_operand( intptr_t &inst_num, const char * &inst_operand ); |
|
523 |
|
524 // Utilities |
|
525 void dump(); |
|
526 void output(FILE *fp); |
|
527 }; |
|
528 |
|
529 |
|
530 class PeepChild : public Form { |
|
531 public: |
|
532 const int _inst_num; // Number of instruction (-1 if only named) |
|
533 const char *_inst_op; // Instruction's operand, NULL if number == -1 |
|
534 const char *_inst_name; // Name of the instruction |
|
535 |
|
536 public: |
|
537 PeepChild(char *inst_name) |
|
538 : _inst_num(-1), _inst_op(NULL), _inst_name(inst_name) {}; |
|
539 PeepChild(int inst_num, char *inst_op, char *inst_name) |
|
540 : _inst_num(inst_num), _inst_op(inst_op), _inst_name(inst_name) {}; |
|
541 ~PeepChild(); |
|
542 |
|
543 bool use_leaf_operand() { return _inst_num != -1; }; |
|
544 bool generate_an_instruction() { return _inst_num == -1; } |
|
545 |
|
546 void dump(); |
|
547 void output(FILE *fp); |
|
548 }; |