duke@435: /* duke@435: * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: // FORMSOPT.HPP - ADL Parser Target Specific Optimization Forms Classes duke@435: duke@435: // Class List duke@435: class Form; duke@435: class InstructForm; duke@435: class OperandForm; duke@435: class OpClassForm; duke@435: class AttributeForm; duke@435: class RegisterForm; duke@435: class PipelineForm; duke@435: class SourceForm; duke@435: class EncodeForm; duke@435: class Component; duke@435: class Constraint; duke@435: class Predicate; duke@435: class MatchRule; duke@435: class Attribute; duke@435: class Effect; duke@435: class ExpandRule; duke@435: class RewriteRule; duke@435: class ConstructRule; duke@435: class FormatRule; duke@435: class Peephole; duke@435: class PeepMatch; duke@435: class PeepConstraint; duke@435: class EncClass; duke@435: class Interface; duke@435: class RegInterface; duke@435: class ConstInterface; duke@435: class MemInterface; duke@435: class CondInterface; duke@435: class Opcode; duke@435: class InsEncode; duke@435: class RegDef; duke@435: class RegClass; duke@435: class AllocClass; duke@435: class ResourceForm; duke@435: class PipeClassForm; duke@435: class PipeClassOperandForm; duke@435: class PipeClassResourceForm; duke@435: class PeepMatch; duke@435: class PeepConstraint; duke@435: class PeepReplace; duke@435: class MatchList; duke@435: duke@435: class ArchDesc; duke@435: duke@435: //==============================Register Allocation============================ duke@435: //------------------------------RegisterForm----------------------------------- duke@435: class RegisterForm : public Form { duke@435: private: duke@435: AllocClass *_current_ac; // State used by iter_RegDefs() duke@435: duke@435: public: duke@435: // Public Data duke@435: NameList _rdefs; // List of register definition names duke@435: Dict _regDef; // map register name to RegDef* duke@435: duke@435: NameList _rclasses; // List of register class names duke@435: Dict _regClass; // map register class name to RegClass* duke@435: duke@435: NameList _aclasses; // List of allocation class names duke@435: Dict _allocClass; // Dictionary of allocation classes duke@435: duke@435: static int _reg_ctr; // Register counter duke@435: static int RegMask_Size(); // Compute RegMask size duke@435: duke@435: // Public Methods duke@435: RegisterForm(); duke@435: ~RegisterForm(); duke@435: duke@435: void addRegDef(char *regName, char *callingConv, char *c_conv, duke@435: char * idealtype, char *encoding, char* concreteName); duke@435: RegClass *addRegClass(const char *className); duke@435: AllocClass *addAllocClass(char *allocName); duke@435: void addSpillRegClass(); duke@435: duke@435: // Provide iteration over all register definitions duke@435: // in the order used by the register allocator duke@435: void reset_RegDefs(); duke@435: RegDef *iter_RegDefs(); duke@435: RegDef *getRegDef (const char *regName); duke@435: duke@435: RegClass *getRegClass(const char *className); duke@435: duke@435: // Return register mask, compressed chunk and register # duke@435: uint reg_mask(char *register_class); duke@435: duke@435: // Check that register classes are compatible with chunks duke@435: bool verify(); duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------RegDef----------------------------------------- duke@435: class RegDef : public Form { duke@435: public: duke@435: // Public Data duke@435: const char *_regname; // ADLC (Opto) Register name duke@435: const char *_callconv; // Calling convention duke@435: const char *_c_conv; // Native calling convention, 'C' duke@435: const char *_idealtype; // Ideal Type for register save/restore duke@435: const char *_concrete; // concrete register name duke@435: duke@435: private: duke@435: const char *_register_encode; // The register encoding duke@435: // The chunk and register mask bits define info for register allocation duke@435: uint32 _register_num; // Which register am I duke@435: duke@435: public: duke@435: // Public Methods duke@435: RegDef(char *regname, char *callconv, char *c_conv, duke@435: char *idealtype, char *encoding, char *concrete); duke@435: ~RegDef(); // Destructor duke@435: duke@435: // Interface to define/redefine the register number duke@435: void set_register_num(uint32 new_register_num); duke@435: duke@435: // Bit pattern used for generating machine code duke@435: const char *register_encode() const; duke@435: // Register number used in machine-independent code duke@435: uint32 register_num() const; duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------RegClass--------------------------------------- duke@435: class RegClass : public Form { duke@435: public: duke@435: // Public Data duke@435: const char *_classid; // Name of class duke@435: NameList _regDefs; // List of registers in class duke@435: Dict _regDef; // Dictionary of registers in class duke@435: bool _stack_or_reg; // Allowed on any stack slot duke@435: duke@435: // Public Methods duke@435: RegClass(const char *classid);// Constructor duke@435: duke@435: void addReg(RegDef *regDef); // Add a register to this class duke@435: duke@435: uint size() const; // Number of registers in class duke@435: int regs_in_word( int wordnum, bool stack_also ); duke@435: duke@435: const RegDef *get_RegDef(const char *regDef_name) const; duke@435: duke@435: // Returns the lowest numbered register in the mask. duke@435: const RegDef* find_first_elem(); duke@435: duke@435: // Iteration support duke@435: void reset(); // Reset the following two iterators duke@435: RegDef *RegDef_iter(); // which move jointly, duke@435: const char *rd_name_iter(); // invoking either advances both. duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------AllocClass------------------------------------- duke@435: class AllocClass : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: char *_classid; // Name of class duke@435: NameList _regDefs; // List of registers in class duke@435: Dict _regDef; // Dictionary of registers in class duke@435: duke@435: // Public Methods duke@435: AllocClass(char *classid); // Constructor duke@435: duke@435: void addReg(RegDef *regDef); // Add a register to this class duke@435: uint size() {return _regDef.Size();} // Number of registers in class duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: duke@435: //==============================Frame Handling================================ duke@435: //------------------------------FrameForm------------------------------------- duke@435: class FrameForm : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: bool _direction; // Direction of stack growth duke@435: char *_sync_stack_slots; duke@435: char *_inline_cache_reg; duke@435: char *_interpreter_method_oop_reg; duke@435: char *_interpreter_frame_pointer_reg; duke@435: char *_cisc_spilling_operand_name; duke@435: char *_frame_pointer; duke@435: char *_c_frame_pointer; duke@435: char *_alignment; duke@435: bool _return_addr_loc; duke@435: bool _c_return_addr_loc; duke@435: char *_return_addr; duke@435: char *_c_return_addr; duke@435: char *_in_preserve_slots; duke@435: char *_varargs_C_out_slots_killed; duke@435: char *_calling_convention; duke@435: char *_c_calling_convention; duke@435: char *_return_value; duke@435: char *_c_return_value; duke@435: duke@435: // Public Methods duke@435: FrameForm(); duke@435: ~FrameForm(); duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: duke@435: //==============================Scheduling===================================== duke@435: //------------------------------PipelineForm----------------------------------- duke@435: class PipelineForm : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: NameList _reslist; // List of pipeline resources duke@435: FormDict _resdict; // Resource Name -> ResourceForm mapping duke@435: int _rescount; // Number of resources (ignores OR cases) duke@435: int _maxcycleused; // Largest cycle used relative to beginning of instruction duke@435: duke@435: NameList _stages; // List of pipeline stages on architecture duke@435: int _stagecnt; // Number of stages listed duke@435: duke@435: NameList _classlist; // List of pipeline classes duke@435: FormDict _classdict; // Class Name -> PipeClassForm mapping duke@435: int _classcnt; // Number of classes duke@435: duke@435: NameList _noplist; // List of NOP instructions duke@435: int _nopcnt; // Number of nop instructions duke@435: duke@435: bool _variableSizeInstrs; // Indicates if this architecture has variable sized instructions duke@435: bool _branchHasDelaySlot; // Indicates that branches have delay slot instructions duke@435: int _maxInstrsPerBundle; // Indicates the maximum number of instructions for ILP duke@435: int _maxBundlesPerCycle; // Indicates the maximum number of bundles for ILP duke@435: int _instrUnitSize; // The minimum instruction unit size, in bytes duke@435: int _bundleUnitSize; // The bundle unit size, in bytes duke@435: int _instrFetchUnitSize; // The size of the I-fetch unit, in bytes [must be power of 2] duke@435: int _instrFetchUnits; // The number of I-fetch units processed per cycle duke@435: duke@435: // Public Methods duke@435: PipelineForm(); duke@435: ~PipelineForm(); duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------ResourceForm----------------------------------- duke@435: class ResourceForm : public Form { duke@435: public: duke@435: unsigned mask() const { return _resmask; }; duke@435: duke@435: private: duke@435: // Public Data duke@435: unsigned _resmask; // Resource Mask (OR of resource specifier bits) duke@435: duke@435: public: duke@435: duke@435: // Virtual Methods duke@435: virtual ResourceForm *is_resource() const; duke@435: duke@435: // Public Methods duke@435: ResourceForm(unsigned resmask); // Constructor duke@435: ~ResourceForm(); // Destructor duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------PipeClassOperandForm----------------------------- duke@435: class PipeClassOperandForm : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_stage; // Name of Stage duke@435: unsigned _iswrite; // Read or Write duke@435: unsigned _more_instrs; // Additional Instructions duke@435: duke@435: // Public Methods duke@435: PipeClassOperandForm(const char *stage, unsigned iswrite, unsigned more_instrs) duke@435: : _stage(stage) duke@435: , _iswrite(iswrite) duke@435: , _more_instrs(more_instrs) duke@435: {}; duke@435: duke@435: ~PipeClassOperandForm() {}; // Destructor duke@435: duke@435: bool isWrite() const { return _iswrite != 0; } duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------PipeClassResourceForm-------------------------- duke@435: class PipeClassResourceForm : public Form { duke@435: private: duke@435: duke@435: public: duke@435: // Public Data duke@435: const char *_resource; // Resource duke@435: const char *_stage; // Stage the resource is used in duke@435: int _cycles; // Number of cycles the resource is used duke@435: duke@435: // Public Methods duke@435: PipeClassResourceForm(const char *resource, const char *stage, int cycles) duke@435: // Constructor duke@435: : _resource(resource) duke@435: , _stage(stage) duke@435: , _cycles(cycles) duke@435: {}; duke@435: duke@435: ~PipeClassResourceForm() {}; // Destructor duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: //------------------------------PipeClassForm---------------------------------- duke@435: class PipeClassForm : public Form { duke@435: private: duke@435: duke@435: public: duke@435: duke@435: // Public Data duke@435: const char *_ident; // Name of class duke@435: int _num; // Used in name of MachNode subclass duke@435: NameList _parameters; // Locally defined names duke@435: FormDict _localNames; // Table of operands & their types duke@435: FormDict _localUsage; // Table of operand usage duke@435: FormList _resUsage; // List of resource usage duke@435: NameList _instructs; // List of instructions and machine nodes that use this pipeline class duke@435: bool _has_fixed_latency; // Always takes this number of cycles duke@435: int _fixed_latency; // Always takes this number of cycles duke@435: int _instruction_count; // Number of instructions in first bundle duke@435: bool _has_multiple_bundles; // Indicates if 1 or multiple bundles duke@435: bool _has_branch_delay_slot; // Has branch delay slot as last instruction duke@435: bool _force_serialization; // This node serializes relative to surrounding nodes duke@435: bool _may_have_no_code; // This node may generate no code based on register allocation duke@435: duke@435: // Virtual Methods duke@435: virtual PipeClassForm *is_pipeclass() const; duke@435: duke@435: // Public Methods duke@435: PipeClassForm(const char *id, int num); duke@435: // Constructor duke@435: ~PipeClassForm(); // Destructor duke@435: duke@435: bool hasFixedLatency() { return _has_fixed_latency; } duke@435: int fixedLatency() { return _fixed_latency; } duke@435: duke@435: void setFixedLatency(int fixed_latency) { _has_fixed_latency = 1; _fixed_latency = fixed_latency; } duke@435: duke@435: void setInstructionCount(int i) { _instruction_count = i; } duke@435: void setMultipleBundles(bool b) { _has_multiple_bundles = b; } duke@435: void setBranchDelay(bool s) { _has_branch_delay_slot = s; } duke@435: void setForceSerialization(bool s) { _force_serialization = s; } duke@435: void setMayHaveNoCode(bool s) { _may_have_no_code = s; } duke@435: duke@435: int InstructionCount() const { return _instruction_count; } duke@435: bool hasMultipleBundles() const { return _has_multiple_bundles; } duke@435: bool hasBranchDelay() const { return _has_branch_delay_slot; } duke@435: bool forceSerialization() const { return _force_serialization; } duke@435: bool mayHaveNoCode() const { return _may_have_no_code; } duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: duke@435: //==============================Peephole Optimization========================== duke@435: //------------------------------Peephole--------------------------------------- duke@435: class Peephole : public Form { duke@435: private: duke@435: static int _peephole_counter;// Incremented by each peephole rule parsed duke@435: int _peephole_number;// Remember my order in architecture description duke@435: PeepMatch *_match; // Instruction pattern to match duke@435: PeepConstraint *_constraint; // List of additional constraints duke@435: PeepReplace *_replace; // Instruction pattern to substitute in duke@435: duke@435: Peephole *_next; duke@435: duke@435: public: duke@435: // Public Methods duke@435: Peephole(); duke@435: ~Peephole(); duke@435: duke@435: // Append a peephole rule with the same root instruction duke@435: void append_peephole(Peephole *next_peephole); duke@435: duke@435: // Store the components of this peephole rule duke@435: void add_match(PeepMatch *only_one_match); duke@435: void append_constraint(PeepConstraint *next_constraint); duke@435: void add_replace(PeepReplace *only_one_replacement); duke@435: duke@435: // Access the components of this peephole rule duke@435: int peephole_number() { return _peephole_number; } duke@435: PeepMatch *match() { return _match; } duke@435: PeepConstraint *constraints() { return _constraint; } duke@435: PeepReplace *replacement() { return _replace; } duke@435: Peephole *next() { return _next; } duke@435: duke@435: void dump(); // Debug printer duke@435: void output(FILE *fp); // Write info to output files duke@435: }; duke@435: duke@435: duke@435: class PeepMatch : public Form { duke@435: private: duke@435: char *_rule; duke@435: // NameList _depth; // Depth of this instruction duke@435: NameList _parent; duke@435: NameList _position; duke@435: NameList _instrs; // List of instructions in match rule duke@435: NameList _input; // input position in parent's instruction duke@435: int _max_position; duke@435: duke@435: public: duke@435: // Public Methods duke@435: PeepMatch(char *rule); duke@435: ~PeepMatch(); duke@435: duke@435: // Insert info into the match-rule duke@435: void add_instruction(int parent, int position, const char *name, int input); duke@435: duke@435: // Access info about instructions in the peep-match rule duke@435: int max_position(); duke@435: const char *instruction_name(intptr_t position); duke@435: // Iterate through all info on matched instructions duke@435: void reset(); duke@435: void next_instruction( intptr_t &parent, intptr_t &position, const char * &name, intptr_t &input ); duke@435: // 'true' if current position in iteration is a placeholder, not matched. duke@435: bool is_placeholder(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: duke@435: class PeepConstraint : public Form { duke@435: private: duke@435: PeepConstraint *_next; // Additional constraints ANDed together duke@435: duke@435: public: duke@435: const intptr_t _left_inst; duke@435: const char *_left_op; duke@435: const char *_relation; duke@435: const intptr_t _right_inst; duke@435: const char *_right_op; duke@435: duke@435: public: duke@435: // Public Methods duke@435: PeepConstraint(intptr_t left_inst, char *left_op, char *relation, duke@435: intptr_t right_inst, char *right_op); duke@435: ~PeepConstraint(); duke@435: duke@435: // Check if constraints use instruction at position duke@435: bool constrains_instruction(intptr_t position); duke@435: duke@435: // Add another constraint duke@435: void append(PeepConstraint *next_peep_constraint); duke@435: // Access the next constraint in the list duke@435: PeepConstraint *next(); duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: duke@435: class PeepReplace : public Form { duke@435: private: duke@435: char *_rule; duke@435: NameList _instruction; duke@435: NameList _operand_inst_num; duke@435: NameList _operand_op_name; duke@435: duke@435: public: duke@435: duke@435: // Public Methods duke@435: PeepReplace(char *rule); duke@435: ~PeepReplace(); duke@435: duke@435: // Add contents of peepreplace duke@435: void add_instruction(char *root); duke@435: void add_operand( int inst_num, char *inst_operand ); duke@435: duke@435: // Access contents of peepreplace duke@435: void reset(); duke@435: void next_instruction(const char * &root); duke@435: void next_operand( intptr_t &inst_num, const char * &inst_operand ); duke@435: duke@435: // Utilities duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: }; duke@435: duke@435: duke@435: class PeepChild : public Form { duke@435: public: duke@435: const int _inst_num; // Number of instruction (-1 if only named) duke@435: const char *_inst_op; // Instruction's operand, NULL if number == -1 duke@435: const char *_inst_name; // Name of the instruction duke@435: duke@435: public: duke@435: PeepChild(char *inst_name) duke@435: : _inst_num(-1), _inst_op(NULL), _inst_name(inst_name) {}; duke@435: PeepChild(int inst_num, char *inst_op, char *inst_name) duke@435: : _inst_num(inst_num), _inst_op(inst_op), _inst_name(inst_name) {}; duke@435: ~PeepChild(); duke@435: duke@435: bool use_leaf_operand() { return _inst_num != -1; }; duke@435: bool generate_an_instruction() { return _inst_num == -1; } duke@435: duke@435: void dump(); duke@435: void output(FILE *fp); duke@435: };