Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/adlc/formsopt.hpp
32285 views
/*1* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_ADLC_FORMSOPT_HPP25#define SHARE_VM_ADLC_FORMSOPT_HPP2627// FORMSOPT.HPP - ADL Parser Target Specific Optimization Forms Classes2829// Class List30class Form;31class InstructForm;32class OperandForm;33class OpClassForm;34class AttributeForm;35class RegisterForm;36class PipelineForm;37class SourceForm;38class EncodeForm;39class Component;40class Constraint;41class Predicate;42class MatchRule;43class Attribute;44class Effect;45class ExpandRule;46class RewriteRule;47class ConstructRule;48class FormatRule;49class Peephole;50class PeepMatch;51class PeepConstraint;52class EncClass;53class Interface;54class RegInterface;55class ConstInterface;56class MemInterface;57class CondInterface;58class Opcode;59class InsEncode;60class RegDef;61class RegClass;62class CodeSnippetRegClass;63class ConditionalRegClass;64class AllocClass;65class ResourceForm;66class PipeClassForm;67class PipeClassOperandForm;68class PipeClassResourceForm;69class PeepMatch;70class PeepConstraint;71class PeepReplace;72class MatchList;7374class ArchDesc;7576//==============================Register Allocation============================77//------------------------------RegisterForm-----------------------------------78class RegisterForm : public Form {79private:80AllocClass *_current_ac; // State used by iter_RegDefs()8182public:83// Public Data84NameList _rdefs; // List of register definition names85Dict _regDef; // map register name to RegDef*8687NameList _rclasses; // List of register class names88Dict _regClass; // map register class name to RegClass*8990NameList _aclasses; // List of allocation class names91Dict _allocClass; // Dictionary of allocation classes9293static int _reg_ctr; // Register counter94static int RegMask_Size(); // Compute RegMask size9596// Public Methods97RegisterForm();98~RegisterForm();99100void addRegDef(char *regName, char *callingConv, char *c_conv,101char * idealtype, char *encoding, char* concreteName);102template<typename T> T* addRegClass(const char* className);103104AllocClass *addAllocClass(char *allocName);105void addSpillRegClass();106107// Provide iteration over all register definitions108// in the order used by the register allocator109void reset_RegDefs();110RegDef *iter_RegDefs();111RegDef *getRegDef (const char *regName);112113RegClass *getRegClass(const char *className);114115// Return register mask, compressed chunk and register #116uint reg_mask(char *register_class);117118// Check that register classes are compatible with chunks119bool verify();120121void dump(); // Debug printer122void output(FILE *fp); // Write info to output files123};124125//------------------------------RegDef-----------------------------------------126class RegDef : public Form {127public:128// Public Data129const char *_regname; // ADLC (Opto) Register name130const char *_callconv; // Calling convention131const char *_c_conv; // Native calling convention, 'C'132const char *_idealtype; // Ideal Type for register save/restore133const char *_concrete; // concrete register name134135private:136const char *_register_encode; // The register encoding137// The chunk and register mask bits define info for register allocation138uint32 _register_num; // Which register am I139140public:141// Public Methods142RegDef(char *regname, char *callconv, char *c_conv,143char *idealtype, char *encoding, char *concrete);144~RegDef(); // Destructor145146// Interface to define/redefine the register number147void set_register_num(uint32 new_register_num);148149// Bit pattern used for generating machine code150const char *register_encode() const;151// Register number used in machine-independent code152uint32 register_num() const;153154void dump(); // Debug printer155void output(FILE *fp); // Write info to output files156};157158//------------------------------RegClass---------------------------------------159// Generic register class. This register class is the internal representation160// for the following .ad file format:161//162// reg_class ptr(RAX, RBX, ...);163//164// where ptr is the name of the register class, RAX and RBX are registers.165//166// This register class allows registers to be spilled onto the stack. Spilling167// is allowed is field _stack_or_reg is true.168class RegClass : public Form {169public:170// Public Data171const char *_classid; // Name of class172NameList _regDefs; // List of registers in class173Dict _regDef; // Dictionary of registers in class174protected:175bool _stack_or_reg; // Allowed on any stack slot176177public:178// Public Methods179RegClass(const char *classid);// Constructor180virtual ~RegClass();181182void addReg(RegDef *regDef); // Add a register to this class183184uint size() const; // Number of registers in class185int regs_in_word( int wordnum, bool stack_also );186187const RegDef *get_RegDef(const char *regDef_name) const;188189// Returns the lowest numbered register in the mask.190const RegDef* find_first_elem();191192// Iteration support193void reset(); // Reset the following two iterators194RegDef *RegDef_iter(); // which move jointly,195const char *rd_name_iter(); // invoking either advances both.196197void dump(); // Debug printer198void output(FILE *fp); // Write info to output files199200virtual bool has_stack_version() {201return _stack_or_reg;202}203virtual void set_stack_version(bool flag) {204_stack_or_reg = flag;205}206207virtual void declare_register_masks(FILE* fp);208virtual void build_register_masks(FILE* fp);209};210211//------------------------------CodeSnippetRegClass----------------------------212// Register class that has an user-defined C++ code snippet attached to it213// to determine at runtime which register class to use. This register class is214// the internal representation for the following .ad file format:215//216// reg_class actual_dflt_reg %{217// if (VM_Version::has_vfp3_32()) {218// return DFLT_REG_mask();219// } else {220// return DFLT_LOW_REG_mask();221// }222// %}223//224// where DFLT_REG_mask() and DFLT_LOW_REG_mask() are the internal names of the225// masks of register classes dflt_reg and dflt_low_reg.226//227// The attached code snippet can select also between more than two register classes.228// This register class can be, however, used only if the register class is not229// cisc-spillable (i.e., the registers of this class are not allowed on the stack,230// which is equivalent with _stack_or_reg being false).231class CodeSnippetRegClass : public RegClass {232protected:233char* _code_snippet;234public:235CodeSnippetRegClass(const char* classid);// Constructor236~CodeSnippetRegClass();237238void set_code_snippet(char* code) {239_code_snippet = code;240}241char* code_snippet() {242return _code_snippet;243}244void set_stack_version(bool flag) {245assert(false, "User defined register classes are not allowed to spill to the stack.");246}247void declare_register_masks(FILE* fp);248void build_register_masks(FILE* fp) {249// We do not need to generate register masks because we select at runtime250// between register masks generated for other register classes.251return;252}253};254255//------------------------------ConditionalRegClass----------------------------256// Register class that has two register classes and a runtime condition attached257// to it. The condition is evaluated at runtime and either one of the register258// attached register classes is selected. This register class is the internal259// representation for the following .ad format:260//261// reg_class_dynamic actual_dflt_reg(dflt_reg, low_reg,262// %{ VM_Version::has_vfp3_32() }%263// );264//265// This example is equivalent to the example used with the CodeSnippetRegClass266// register class. A ConditionalRegClass works also if a register class is cisc-spillable267// (i.e., _stack_or_reg is true), but if can select only between two register classes.268class ConditionalRegClass : public RegClass {269protected:270// reference to condition code271char* _condition_code; // C++ condition code to dynamically determine which register class to use.272273// Example syntax (equivalent to previous example):274//275// reg_class actual_dflt_reg(dflt_reg, low_reg,276// %{ VM_Version::has_vfp3_32() }%277// );278// reference to conditional register classes279RegClass* _rclasses[2]; // 0 is the register class selected if the condition code returns true280// 1 is the register class selected if the condition code returns false281public:282ConditionalRegClass(const char* classid);// Constructor283~ConditionalRegClass();284285virtual void set_stack_version(bool flag) {286RegClass::set_stack_version(flag);287assert((_rclasses[0] != NULL), "Register class NULL for condition code == true");288assert((_rclasses[1] != NULL), "Register class NULL for condition code == false");289_rclasses[0]->set_stack_version(flag);290_rclasses[1]->set_stack_version(flag);291}292void declare_register_masks(FILE* fp);293void build_register_masks(FILE* fp) {294// We do not need to generate register masks because we select at runtime295// between register masks generated for other register classes.296return;297}298void set_rclass_at_index(int index, RegClass* rclass) {299assert((0 <= index && index < 2), "Condition code can select only between two register classes");300_rclasses[index] = rclass;301}302void set_condition_code(char* code) {303_condition_code = code;304}305char* condition_code() {306return _condition_code;307}308};309310//------------------------------AllocClass-------------------------------------311class AllocClass : public Form {312private:313314public:315// Public Data316char *_classid; // Name of class317NameList _regDefs; // List of registers in class318Dict _regDef; // Dictionary of registers in class319320// Public Methods321AllocClass(char *classid); // Constructor322323void addReg(RegDef *regDef); // Add a register to this class324uint size() {return _regDef.Size();} // Number of registers in class325326void dump(); // Debug printer327void output(FILE *fp); // Write info to output files328};329330331//==============================Frame Handling================================332//------------------------------FrameForm-------------------------------------333class FrameForm : public Form {334private:335336public:337// Public Data338bool _direction; // Direction of stack growth339char *_sync_stack_slots;340char *_inline_cache_reg;341char *_interpreter_method_oop_reg;342char *_interpreter_frame_pointer_reg;343char *_cisc_spilling_operand_name;344char *_frame_pointer;345char *_c_frame_pointer;346char *_alignment;347bool _return_addr_loc;348bool _c_return_addr_loc;349char *_return_addr;350char *_c_return_addr;351char *_in_preserve_slots;352char *_varargs_C_out_slots_killed;353char *_calling_convention;354char *_c_calling_convention;355char *_return_value;356char *_c_return_value;357358// Public Methods359FrameForm();360~FrameForm();361362void dump(); // Debug printer363void output(FILE *fp); // Write info to output files364};365366367//==============================Scheduling=====================================368//------------------------------PipelineForm-----------------------------------369class PipelineForm : public Form {370private:371372public:373// Public Data374NameList _reslist; // List of pipeline resources375FormDict _resdict; // Resource Name -> ResourceForm mapping376int _rescount; // Number of resources (ignores OR cases)377int _maxcycleused; // Largest cycle used relative to beginning of instruction378379NameList _stages; // List of pipeline stages on architecture380int _stagecnt; // Number of stages listed381382NameList _classlist; // List of pipeline classes383FormDict _classdict; // Class Name -> PipeClassForm mapping384int _classcnt; // Number of classes385386NameList _noplist; // List of NOP instructions387int _nopcnt; // Number of nop instructions388389bool _variableSizeInstrs; // Indicates if this architecture has variable sized instructions390bool _branchHasDelaySlot; // Indicates that branches have delay slot instructions391int _maxInstrsPerBundle; // Indicates the maximum number of instructions for ILP392int _maxBundlesPerCycle; // Indicates the maximum number of bundles for ILP393int _instrUnitSize; // The minimum instruction unit size, in bytes394int _bundleUnitSize; // The bundle unit size, in bytes395int _instrFetchUnitSize; // The size of the I-fetch unit, in bytes [must be power of 2]396int _instrFetchUnits; // The number of I-fetch units processed per cycle397398// Public Methods399PipelineForm();400~PipelineForm();401402void dump(); // Debug printer403void output(FILE *fp); // Write info to output files404};405406//------------------------------ResourceForm-----------------------------------407class ResourceForm : public Form {408public:409unsigned mask() const { return _resmask; };410411private:412// Public Data413unsigned _resmask; // Resource Mask (OR of resource specifier bits)414415public:416417// Virtual Methods418virtual ResourceForm *is_resource() const;419420// Public Methods421ResourceForm(unsigned resmask); // Constructor422~ResourceForm(); // Destructor423424void dump(); // Debug printer425void output(FILE *fp); // Write info to output files426};427428//------------------------------PipeClassOperandForm-----------------------------429class PipeClassOperandForm : public Form {430private:431432public:433// Public Data434const char *_stage; // Name of Stage435unsigned _iswrite; // Read or Write436unsigned _more_instrs; // Additional Instructions437438// Public Methods439PipeClassOperandForm(const char *stage, unsigned iswrite, unsigned more_instrs)440: _stage(stage)441, _iswrite(iswrite)442, _more_instrs(more_instrs)443{};444445~PipeClassOperandForm() {}; // Destructor446447bool isWrite() const { return _iswrite != 0; }448449void dump(); // Debug printer450void output(FILE *fp); // Write info to output files451};452453//------------------------------PipeClassResourceForm--------------------------454class PipeClassResourceForm : public Form {455private:456457public:458// Public Data459const char *_resource; // Resource460const char *_stage; // Stage the resource is used in461int _cycles; // Number of cycles the resource is used462463// Public Methods464PipeClassResourceForm(const char *resource, const char *stage, int cycles)465// Constructor466: _resource(resource)467, _stage(stage)468, _cycles(cycles)469{};470471~PipeClassResourceForm() {}; // Destructor472473void dump(); // Debug printer474void output(FILE *fp); // Write info to output files475};476477//------------------------------PipeClassForm----------------------------------478class PipeClassForm : public Form {479private:480481public:482483// Public Data484const char *_ident; // Name of class485int _num; // Used in name of MachNode subclass486NameList _parameters; // Locally defined names487FormDict _localNames; // Table of operands & their types488FormDict _localUsage; // Table of operand usage489FormList _resUsage; // List of resource usage490NameList _instructs; // List of instructions and machine nodes that use this pipeline class491bool _has_fixed_latency; // Always takes this number of cycles492int _fixed_latency; // Always takes this number of cycles493int _instruction_count; // Number of instructions in first bundle494bool _has_multiple_bundles; // Indicates if 1 or multiple bundles495bool _has_branch_delay_slot; // Has branch delay slot as last instruction496bool _force_serialization; // This node serializes relative to surrounding nodes497bool _may_have_no_code; // This node may generate no code based on register allocation498499// Virtual Methods500virtual PipeClassForm *is_pipeclass() const;501502// Public Methods503PipeClassForm(const char *id, int num);504// Constructor505~PipeClassForm(); // Destructor506507bool hasFixedLatency() { return _has_fixed_latency; }508int fixedLatency() { return _fixed_latency; }509510void setFixedLatency(int fixed_latency) { _has_fixed_latency = 1; _fixed_latency = fixed_latency; }511512void setInstructionCount(int i) { _instruction_count = i; }513void setMultipleBundles(bool b) { _has_multiple_bundles = b; }514void setBranchDelay(bool s) { _has_branch_delay_slot = s; }515void setForceSerialization(bool s) { _force_serialization = s; }516void setMayHaveNoCode(bool s) { _may_have_no_code = s; }517518int InstructionCount() const { return _instruction_count; }519bool hasMultipleBundles() const { return _has_multiple_bundles; }520bool hasBranchDelay() const { return _has_branch_delay_slot; }521bool forceSerialization() const { return _force_serialization; }522bool mayHaveNoCode() const { return _may_have_no_code; }523524void dump(); // Debug printer525void output(FILE *fp); // Write info to output files526};527528529//==============================Peephole Optimization==========================530//------------------------------Peephole---------------------------------------531class Peephole : public Form {532private:533static int _peephole_counter;// Incremented by each peephole rule parsed534int _peephole_number;// Remember my order in architecture description535PeepMatch *_match; // Instruction pattern to match536PeepConstraint *_constraint; // List of additional constraints537PeepReplace *_replace; // Instruction pattern to substitute in538539Peephole *_next;540541public:542// Public Methods543Peephole();544~Peephole();545546// Append a peephole rule with the same root instruction547void append_peephole(Peephole *next_peephole);548549// Store the components of this peephole rule550void add_match(PeepMatch *only_one_match);551void append_constraint(PeepConstraint *next_constraint);552void add_replace(PeepReplace *only_one_replacement);553554// Access the components of this peephole rule555int peephole_number() { return _peephole_number; }556PeepMatch *match() { return _match; }557PeepConstraint *constraints() { return _constraint; }558PeepReplace *replacement() { return _replace; }559Peephole *next() { return _next; }560561void dump(); // Debug printer562void output(FILE *fp); // Write info to output files563};564565566class PeepMatch : public Form {567private:568char *_rule;569// NameList _depth; // Depth of this instruction570NameList _parent;571NameList _position;572NameList _instrs; // List of instructions in match rule573NameList _input; // input position in parent's instruction574int _max_position;575576public:577// Public Methods578PeepMatch(char *rule);579~PeepMatch();580581// Insert info into the match-rule582void add_instruction(int parent, int position, const char *name, int input);583584// Access info about instructions in the peep-match rule585int max_position();586const char *instruction_name(int position);587// Iterate through all info on matched instructions588void reset();589void next_instruction(int &parent, int &position, const char* &name, int &input);590// 'true' if current position in iteration is a placeholder, not matched.591bool is_placeholder();592593void dump();594void output(FILE *fp);595};596597598class PeepConstraint : public Form {599private:600PeepConstraint *_next; // Additional constraints ANDed together601602public:603const int _left_inst;604const char* _left_op;605const char* _relation;606const int _right_inst;607const char* _right_op;608609public:610// Public Methods611PeepConstraint(int left_inst, char* left_op, char* relation,612int right_inst, char* right_op);613~PeepConstraint();614615// Check if constraints use instruction at position616bool constrains_instruction(int position);617618// Add another constraint619void append(PeepConstraint *next_peep_constraint);620// Access the next constraint in the list621PeepConstraint *next();622623void dump();624void output(FILE *fp);625};626627628class PeepReplace : public Form {629private:630char *_rule;631NameList _instruction;632NameList _operand_inst_num;633NameList _operand_op_name;634635public:636637// Public Methods638PeepReplace(char *rule);639~PeepReplace();640641// Add contents of peepreplace642void add_instruction(char *root);643void add_operand( int inst_num, char *inst_operand );644645// Access contents of peepreplace646void reset();647void next_instruction(const char * &root);648void next_operand(int &inst_num, const char * &inst_operand );649650// Utilities651void dump();652void output(FILE *fp);653};654655656class PeepChild : public Form {657public:658const int _inst_num; // Number of instruction (-1 if only named)659const char *_inst_op; // Instruction's operand, NULL if number == -1660const char *_inst_name; // Name of the instruction661662public:663PeepChild(char *inst_name)664: _inst_num(-1), _inst_op(NULL), _inst_name(inst_name) {};665PeepChild(int inst_num, char *inst_op, char *inst_name)666: _inst_num(inst_num), _inst_op(inst_op), _inst_name(inst_name) {};667~PeepChild();668669bool use_leaf_operand() { return _inst_num != -1; };670bool generate_an_instruction() { return _inst_num == -1; }671672void dump();673void output(FILE *fp);674};675676#endif // SHARE_VM_ADLC_FORMSOPT_HPP677678679