Path: blob/master/src/hotspot/share/adlc/formsopt.hpp
41144 views
/*1* Copyright (c) 1998, 2019, 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_ADLC_FORMSOPT_HPP25#define SHARE_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();106void addDynamicRegClass();107108// Provide iteration over all register definitions109// in the order used by the register allocator110void reset_RegDefs();111RegDef *iter_RegDefs();112RegDef *getRegDef (const char *regName);113114RegClass *getRegClass(const char *className);115116// Return register mask, compressed chunk and register #117uint reg_mask(char *register_class);118119// Check that register classes are compatible with chunks120bool verify();121122void dump(); // Debug printer123void output(FILE *fp); // Write info to output files124};125126//------------------------------RegDef-----------------------------------------127class RegDef : public Form {128public:129// Public Data130const char *_regname; // ADLC (Opto) Register name131const char *_callconv; // Calling convention132const char *_c_conv; // Native calling convention, 'C'133const char *_idealtype; // Ideal Type for register save/restore134const char *_concrete; // concrete register name135136private:137const char *_register_encode; // The register encoding138// The chunk and register mask bits define info for register allocation139uint32 _register_num; // Which register am I140141public:142// Public Methods143RegDef(char *regname, char *callconv, char *c_conv,144char *idealtype, char *encoding, char *concrete);145~RegDef(); // Destructor146147// Interface to define/redefine the register number148void set_register_num(uint32 new_register_num);149150// Bit pattern used for generating machine code151const char *register_encode() const;152// Register number used in machine-independent code153uint32 register_num() const;154155void dump(); // Debug printer156void output(FILE *fp); // Write info to output files157};158159//------------------------------RegClass---------------------------------------160// Generic register class. This register class is the internal representation161// for the following .ad file format:162//163// reg_class ptr(RAX, RBX, ...);164//165// where ptr is the name of the register class, RAX and RBX are registers.166//167// This register class allows registers to be spilled onto the stack. Spilling168// is allowed is field _stack_or_reg is true.169class RegClass : public Form {170public:171// Public Data172const char *_classid; // Name of class173NameList _regDefs; // List of registers in class174Dict _regDef; // Dictionary of registers in class175protected:176bool _stack_or_reg; // Allowed on any stack slot177178public:179// Public Methods180RegClass(const char *classid);// Constructor181virtual ~RegClass();182183void addReg(RegDef *regDef); // Add a register to this class184185uint size() const; // Number of registers in class186int regs_in_word( int wordnum, bool stack_also );187188const RegDef *get_RegDef(const char *regDef_name) const;189190// Returns the lowest numbered register in the mask.191const RegDef* find_first_elem();192193// Iteration support194void reset(); // Reset the following two iterators195RegDef *RegDef_iter(); // which move jointly,196const char *rd_name_iter(); // invoking either advances both.197198void dump(); // Debug printer199void output(FILE *fp); // Write info to output files200201virtual bool has_stack_version() {202return _stack_or_reg;203}204virtual void set_stack_version(bool flag) {205_stack_or_reg = flag;206}207208virtual void declare_register_masks(FILE* fp);209virtual void build_register_masks(FILE* fp);210};211212//------------------------------CodeSnippetRegClass----------------------------213// Register class that has an user-defined C++ code snippet attached to it214// to determine at runtime which register class to use. This register class is215// the internal representation for the following .ad file format:216//217// reg_class actual_dflt_reg %{218// if (VM_Version::has_vfp3_32()) {219// return DFLT_REG_mask();220// } else {221// return DFLT_LOW_REG_mask();222// }223// %}224//225// where DFLT_REG_mask() and DFLT_LOW_REG_mask() are the internal names of the226// masks of register classes dflt_reg and dflt_low_reg.227//228// The attached code snippet can select also between more than two register classes.229// This register class can be, however, used only if the register class is not230// cisc-spillable (i.e., the registers of this class are not allowed on the stack,231// which is equivalent with _stack_or_reg being false).232class CodeSnippetRegClass : public RegClass {233protected:234char* _code_snippet;235public:236CodeSnippetRegClass(const char* classid);// Constructor237~CodeSnippetRegClass();238239void set_code_snippet(char* code) {240_code_snippet = code;241}242char* code_snippet() {243return _code_snippet;244}245void declare_register_masks(FILE* fp);246void build_register_masks(FILE* fp) {247// We do not need to generate register masks because we select at runtime248// between register masks generated for other register classes.249return;250}251};252253//------------------------------ConditionalRegClass----------------------------254// Register class that has two register classes and a runtime condition attached255// to it. The condition is evaluated at runtime and either one of the register256// attached register classes is selected. This register class is the internal257// representation for the following .ad format:258//259// reg_class_dynamic actual_dflt_reg(dflt_reg, low_reg,260// %{ VM_Version::has_vfp3_32() }%261// );262//263// This example is equivalent to the example used with the CodeSnippetRegClass264// register class. A ConditionalRegClass works also if a register class is cisc-spillable265// (i.e., _stack_or_reg is true), but if can select only between two register classes.266class ConditionalRegClass : public RegClass {267protected:268// reference to condition code269char* _condition_code; // C++ condition code to dynamically determine which register class to use.270271// Example syntax (equivalent to previous example):272//273// reg_class actual_dflt_reg(dflt_reg, low_reg,274// %{ VM_Version::has_vfp3_32() }%275// );276// reference to conditional register classes277RegClass* _rclasses[2]; // 0 is the register class selected if the condition code returns true278// 1 is the register class selected if the condition code returns false279public:280ConditionalRegClass(const char* classid);// Constructor281~ConditionalRegClass();282283virtual void set_stack_version(bool flag) {284RegClass::set_stack_version(flag);285assert((_rclasses[0] != NULL), "Register class NULL for condition code == true");286assert((_rclasses[1] != NULL), "Register class NULL for condition code == false");287_rclasses[0]->set_stack_version(flag);288_rclasses[1]->set_stack_version(flag);289}290void declare_register_masks(FILE* fp);291void build_register_masks(FILE* fp) {292// We do not need to generate register masks because we select at runtime293// between register masks generated for other register classes.294return;295}296void set_rclass_at_index(int index, RegClass* rclass) {297assert((0 <= index && index < 2), "Condition code can select only between two register classes");298_rclasses[index] = rclass;299}300void set_condition_code(char* code) {301_condition_code = code;302}303char* condition_code() {304return _condition_code;305}306};307308//------------------------------AllocClass-------------------------------------309class AllocClass : public Form {310private:311312public:313// Public Data314char *_classid; // Name of class315NameList _regDefs; // List of registers in class316Dict _regDef; // Dictionary of registers in class317318// Public Methods319AllocClass(char *classid); // Constructor320321void addReg(RegDef *regDef); // Add a register to this class322uint size() {return _regDef.Size();} // Number of registers in class323324void dump(); // Debug printer325void output(FILE *fp); // Write info to output files326};327328329//==============================Frame Handling================================330//------------------------------FrameForm-------------------------------------331class FrameForm : public Form {332private:333334public:335// Public Data336char *_sync_stack_slots;337char *_inline_cache_reg;338char *_interpreter_frame_pointer_reg;339char *_cisc_spilling_operand_name;340char *_frame_pointer;341char *_c_frame_pointer;342char *_alignment;343bool _return_addr_loc;344bool _c_return_addr_loc;345char *_return_addr;346char *_c_return_addr;347char *_varargs_C_out_slots_killed;348char *_return_value;349char *_c_return_value;350351// Public Methods352FrameForm();353~FrameForm();354355void dump(); // Debug printer356void output(FILE *fp); // Write info to output files357};358359360//==============================Scheduling=====================================361//------------------------------PipelineForm-----------------------------------362class PipelineForm : public Form {363private:364365public:366// Public Data367NameList _reslist; // List of pipeline resources368FormDict _resdict; // Resource Name -> ResourceForm mapping369int _rescount; // Number of resources (ignores OR cases)370int _maxcycleused; // Largest cycle used relative to beginning of instruction371372NameList _stages; // List of pipeline stages on architecture373int _stagecnt; // Number of stages listed374375NameList _classlist; // List of pipeline classes376FormDict _classdict; // Class Name -> PipeClassForm mapping377int _classcnt; // Number of classes378379NameList _noplist; // List of NOP instructions380int _nopcnt; // Number of nop instructions381382bool _variableSizeInstrs; // Indicates if this architecture has variable sized instructions383bool _branchHasDelaySlot; // Indicates that branches have delay slot instructions384int _maxInstrsPerBundle; // Indicates the maximum number of instructions for ILP385int _maxBundlesPerCycle; // Indicates the maximum number of bundles for ILP386int _instrUnitSize; // The minimum instruction unit size, in bytes387int _bundleUnitSize; // The bundle unit size, in bytes388int _instrFetchUnitSize; // The size of the I-fetch unit, in bytes [must be power of 2]389int _instrFetchUnits; // The number of I-fetch units processed per cycle390391// Public Methods392PipelineForm();393~PipelineForm();394395void dump(); // Debug printer396void output(FILE *fp); // Write info to output files397};398399//------------------------------ResourceForm-----------------------------------400class ResourceForm : public Form {401public:402unsigned mask() const { return _resmask; };403404private:405// Public Data406unsigned _resmask; // Resource Mask (OR of resource specifier bits)407408public:409410// Virtual Methods411virtual ResourceForm *is_resource() const;412413// Public Methods414ResourceForm(unsigned resmask); // Constructor415~ResourceForm(); // Destructor416417void dump(); // Debug printer418void output(FILE *fp); // Write info to output files419};420421//------------------------------PipeClassOperandForm-----------------------------422class PipeClassOperandForm : public Form {423private:424425public:426// Public Data427const char *_stage; // Name of Stage428unsigned _iswrite; // Read or Write429unsigned _more_instrs; // Additional Instructions430431// Public Methods432PipeClassOperandForm(const char *stage, unsigned iswrite, unsigned more_instrs)433: _stage(stage)434, _iswrite(iswrite)435, _more_instrs(more_instrs)436{};437438~PipeClassOperandForm() {}; // Destructor439440bool isWrite() const { return _iswrite != 0; }441442void dump(); // Debug printer443void output(FILE *fp); // Write info to output files444};445446//------------------------------PipeClassResourceForm--------------------------447class PipeClassResourceForm : public Form {448private:449450public:451// Public Data452const char *_resource; // Resource453const char *_stage; // Stage the resource is used in454int _cycles; // Number of cycles the resource is used455456// Public Methods457PipeClassResourceForm(const char *resource, const char *stage, int cycles)458// Constructor459: _resource(resource)460, _stage(stage)461, _cycles(cycles)462{};463464~PipeClassResourceForm() {}; // Destructor465466void dump(); // Debug printer467void output(FILE *fp); // Write info to output files468};469470//------------------------------PipeClassForm----------------------------------471class PipeClassForm : public Form {472private:473474public:475476// Public Data477const char *_ident; // Name of class478int _num; // Used in name of MachNode subclass479NameList _parameters; // Locally defined names480FormDict _localNames; // Table of operands & their types481FormDict _localUsage; // Table of operand usage482FormList _resUsage; // List of resource usage483NameList _instructs; // List of instructions and machine nodes that use this pipeline class484bool _has_fixed_latency; // Always takes this number of cycles485int _fixed_latency; // Always takes this number of cycles486int _instruction_count; // Number of instructions in first bundle487bool _has_multiple_bundles; // Indicates if 1 or multiple bundles488bool _has_branch_delay_slot; // Has branch delay slot as last instruction489bool _force_serialization; // This node serializes relative to surrounding nodes490bool _may_have_no_code; // This node may generate no code based on register allocation491492// Virtual Methods493virtual PipeClassForm *is_pipeclass() const;494495// Public Methods496PipeClassForm(const char *id, int num);497// Constructor498~PipeClassForm(); // Destructor499500bool hasFixedLatency() { return _has_fixed_latency; }501int fixedLatency() { return _fixed_latency; }502503void setFixedLatency(int fixed_latency) { _has_fixed_latency = 1; _fixed_latency = fixed_latency; }504505void setInstructionCount(int i) { _instruction_count = i; }506void setMultipleBundles(bool b) { _has_multiple_bundles = b; }507void setBranchDelay(bool s) { _has_branch_delay_slot = s; }508void setForceSerialization(bool s) { _force_serialization = s; }509void setMayHaveNoCode(bool s) { _may_have_no_code = s; }510511int InstructionCount() const { return _instruction_count; }512bool hasMultipleBundles() const { return _has_multiple_bundles; }513bool hasBranchDelay() const { return _has_branch_delay_slot; }514bool forceSerialization() const { return _force_serialization; }515bool mayHaveNoCode() const { return _may_have_no_code; }516517void dump(); // Debug printer518void output(FILE *fp); // Write info to output files519};520521522//==============================Peephole Optimization==========================523//------------------------------Peephole---------------------------------------524class Peephole : public Form {525private:526static int _peephole_counter;// Incremented by each peephole rule parsed527int _peephole_number;// Remember my order in architecture description528PeepMatch *_match; // Instruction pattern to match529PeepConstraint *_constraint; // List of additional constraints530PeepReplace *_replace; // Instruction pattern to substitute in531532Peephole *_next;533534public:535// Public Methods536Peephole();537~Peephole();538539// Append a peephole rule with the same root instruction540void append_peephole(Peephole *next_peephole);541542// Store the components of this peephole rule543void add_match(PeepMatch *only_one_match);544void append_constraint(PeepConstraint *next_constraint);545void add_replace(PeepReplace *only_one_replacement);546547// Access the components of this peephole rule548int peephole_number() { return _peephole_number; }549PeepMatch *match() { return _match; }550PeepConstraint *constraints() { return _constraint; }551PeepReplace *replacement() { return _replace; }552Peephole *next() { return _next; }553554void dump(); // Debug printer555void output(FILE *fp); // Write info to output files556};557558559class PeepMatch : public Form {560private:561char *_rule;562// NameList _depth; // Depth of this instruction563NameList _parent;564NameList _position;565NameList _instrs; // List of instructions in match rule566NameList _input; // input position in parent's instruction567int _max_position;568569public:570// Public Methods571PeepMatch(char *rule);572~PeepMatch();573574// Insert info into the match-rule575void add_instruction(int parent, int position, const char *name, int input);576577// Access info about instructions in the peep-match rule578int max_position();579const char *instruction_name(int position);580// Iterate through all info on matched instructions581void reset();582void next_instruction(int &parent, int &position, const char* &name, int &input);583// 'true' if current position in iteration is a placeholder, not matched.584bool is_placeholder();585586void dump();587void output(FILE *fp);588};589590591class PeepConstraint : public Form {592private:593PeepConstraint *_next; // Additional constraints ANDed together594595public:596const int _left_inst;597const char* _left_op;598const char* _relation;599const int _right_inst;600const char* _right_op;601602public:603// Public Methods604PeepConstraint(int left_inst, char* left_op, char* relation,605int right_inst, char* right_op);606~PeepConstraint();607608// Check if constraints use instruction at position609bool constrains_instruction(int position);610611// Add another constraint612void append(PeepConstraint *next_peep_constraint);613// Access the next constraint in the list614PeepConstraint *next();615616void dump();617void output(FILE *fp);618};619620621class PeepReplace : public Form {622private:623char *_rule;624NameList _instruction;625NameList _operand_inst_num;626NameList _operand_op_name;627628public:629630// Public Methods631PeepReplace(char *rule);632~PeepReplace();633634// Add contents of peepreplace635void add_instruction(char *root);636void add_operand( int inst_num, char *inst_operand );637638// Access contents of peepreplace639void reset();640void next_instruction(const char * &root);641void next_operand(int &inst_num, const char * &inst_operand );642643// Utilities644void dump();645void output(FILE *fp);646};647648649class PeepChild : public Form {650public:651const int _inst_num; // Number of instruction (-1 if only named)652const char *_inst_op; // Instruction's operand, NULL if number == -1653const char *_inst_name; // Name of the instruction654655public:656PeepChild(char *inst_name)657: _inst_num(-1), _inst_op(NULL), _inst_name(inst_name) {};658PeepChild(int inst_num, char *inst_op, char *inst_name)659: _inst_num(inst_num), _inst_op(inst_op), _inst_name(inst_name) {};660~PeepChild();661662bool use_leaf_operand() { return _inst_num != -1; };663bool generate_an_instruction() { return _inst_num == -1; }664665void dump();666void output(FILE *fp);667};668669#endif // SHARE_ADLC_FORMSOPT_HPP670671672