Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/adlc/formssel.cpp
32285 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// FORMS.CPP - Definitions for ADL Parser Forms Classes25#include "utilities/macros.hpp"26#include "adlc.hpp"2728//==============================Instructions===================================29//------------------------------InstructForm-----------------------------------30InstructForm::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_is_mach_constant(false),35_needs_constant_base(false),36_has_call(false)37{38_ftype = Form::INS;3940_matrule = NULL;41_insencode = NULL;42_constant = NULL;43_is_postalloc_expand = false;44_opcode = NULL;45_size = NULL;46_attribs = NULL;47_predicate = NULL;48_exprule = NULL;49_rewrule = NULL;50_format = NULL;51_peephole = NULL;52_ins_pipe = NULL;53_uniq_idx = NULL;54_num_uniq = 0;55_cisc_spill_operand = Not_cisc_spillable;// Which operand may cisc-spill56_cisc_spill_alternate = NULL; // possible cisc replacement57_cisc_reg_mask_name = NULL;58_is_cisc_alternate = false;59_is_short_branch = false;60_short_branch_form = NULL;61_alignment = 1;62}6364InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule)65: _ident(id), _ideal_only(false),66_localNames(instr->_localNames),67_effects(instr->_effects),68_is_mach_constant(false),69_needs_constant_base(false),70_has_call(false)71{72_ftype = Form::INS;7374_matrule = rule;75_insencode = instr->_insencode;76_constant = instr->_constant;77_is_postalloc_expand = instr->_is_postalloc_expand;78_opcode = instr->_opcode;79_size = instr->_size;80_attribs = instr->_attribs;81_predicate = instr->_predicate;82_exprule = instr->_exprule;83_rewrule = instr->_rewrule;84_format = instr->_format;85_peephole = instr->_peephole;86_ins_pipe = instr->_ins_pipe;87_uniq_idx = instr->_uniq_idx;88_num_uniq = instr->_num_uniq;89_cisc_spill_operand = Not_cisc_spillable; // Which operand may cisc-spill90_cisc_spill_alternate = NULL; // possible cisc replacement91_cisc_reg_mask_name = NULL;92_is_cisc_alternate = false;93_is_short_branch = false;94_short_branch_form = NULL;95_alignment = 1;96// Copy parameters97const char *name;98instr->_parameters.reset();99for (; (name = instr->_parameters.iter()) != NULL;)100_parameters.addName(name);101}102103InstructForm::~InstructForm() {104}105106InstructForm *InstructForm::is_instruction() const {107return (InstructForm*)this;108}109110bool InstructForm::ideal_only() const {111return _ideal_only;112}113114bool InstructForm::sets_result() const {115return (_matrule != NULL && _matrule->sets_result());116}117118bool InstructForm::needs_projections() {119_components.reset();120for( Component *comp; (comp = _components.iter()) != NULL; ) {121if (comp->isa(Component::KILL)) {122return true;123}124}125return false;126}127128129bool InstructForm::has_temps() {130if (_matrule) {131// Examine each component to see if it is a TEMP132_components.reset();133// Skip the first component, if already handled as (SET dst (...))134Component *comp = NULL;135if (sets_result()) comp = _components.iter();136while ((comp = _components.iter()) != NULL) {137if (comp->isa(Component::TEMP)) {138return true;139}140}141}142143return false;144}145146uint InstructForm::num_defs_or_kills() {147uint defs_or_kills = 0;148149_components.reset();150for( Component *comp; (comp = _components.iter()) != NULL; ) {151if( comp->isa(Component::DEF) || comp->isa(Component::KILL) ) {152++defs_or_kills;153}154}155156return defs_or_kills;157}158159// This instruction has an expand rule?160bool InstructForm::expands() const {161return ( _exprule != NULL );162}163164// This instruction has a late expand rule?165bool InstructForm::postalloc_expands() const {166return _is_postalloc_expand;167}168169// This instruction has a peephole rule?170Peephole *InstructForm::peepholes() const {171return _peephole;172}173174// This instruction has a peephole rule?175void InstructForm::append_peephole(Peephole *peephole) {176if( _peephole == NULL ) {177_peephole = peephole;178} else {179_peephole->append_peephole(peephole);180}181}182183184// ideal opcode enumeration185const char *InstructForm::ideal_Opcode( FormDict &globalNames ) const {186if( !_matrule ) return "Node"; // Something weird187// Chain rules do not really have ideal Opcodes; use their source188// operand ideal Opcode instead.189if( is_simple_chain_rule(globalNames) ) {190const char *src = _matrule->_rChild->_opType;191OperandForm *src_op = globalNames[src]->is_operand();192assert( src_op, "Not operand class of chain rule" );193if( !src_op->_matrule ) return "Node";194return src_op->_matrule->_opType;195}196// Operand chain rules do not really have ideal Opcodes197if( _matrule->is_chain_rule(globalNames) )198return "Node";199return strcmp(_matrule->_opType,"Set")200? _matrule->_opType201: _matrule->_rChild->_opType;202}203204// Recursive check on all operands' match rules in my match rule205bool InstructForm::is_pinned(FormDict &globals) {206if ( ! _matrule) return false;207208int index = 0;209if (_matrule->find_type("Goto", index)) return true;210if (_matrule->find_type("If", index)) return true;211if (_matrule->find_type("CountedLoopEnd",index)) return true;212if (_matrule->find_type("Return", index)) return true;213if (_matrule->find_type("Rethrow", index)) return true;214if (_matrule->find_type("TailCall", index)) return true;215if (_matrule->find_type("TailJump", index)) return true;216if (_matrule->find_type("Halt", index)) return true;217if (_matrule->find_type("Jump", index)) return true;218219return is_parm(globals);220}221222// Recursive check on all operands' match rules in my match rule223bool InstructForm::is_projection(FormDict &globals) {224if ( ! _matrule) return false;225226int index = 0;227if (_matrule->find_type("Goto", index)) return true;228if (_matrule->find_type("Return", index)) return true;229if (_matrule->find_type("Rethrow", index)) return true;230if (_matrule->find_type("TailCall",index)) return true;231if (_matrule->find_type("TailJump",index)) return true;232if (_matrule->find_type("Halt", index)) return true;233234return false;235}236237// Recursive check on all operands' match rules in my match rule238bool InstructForm::is_parm(FormDict &globals) {239if ( ! _matrule) return false;240241int index = 0;242if (_matrule->find_type("Parm",index)) return true;243244return false;245}246247bool InstructForm::is_ideal_negD() const {248return (_matrule && _matrule->_rChild && strcmp(_matrule->_rChild->_opType, "NegD") == 0);249}250251// Return 'true' if this instruction matches an ideal 'Copy*' node252int InstructForm::is_ideal_copy() const {253return _matrule ? _matrule->is_ideal_copy() : 0;254}255256// Return 'true' if this instruction is too complex to rematerialize.257int InstructForm::is_expensive() const {258// We can prove it is cheap if it has an empty encoding.259// This helps with platform-specific nops like ThreadLocal and RoundFloat.260if (is_empty_encoding())261return 0;262263if (is_tls_instruction())264return 1;265266if (_matrule == NULL) return 0;267268return _matrule->is_expensive();269}270271// Has an empty encoding if _size is a constant zero or there272// are no ins_encode tokens.273int InstructForm::is_empty_encoding() const {274if (_insencode != NULL) {275_insencode->reset();276if (_insencode->encode_class_iter() == NULL) {277return 1;278}279}280if (_size != NULL && strcmp(_size, "0") == 0) {281return 1;282}283return 0;284}285286int InstructForm::is_tls_instruction() const {287if (_ident != NULL &&288( ! strcmp( _ident,"tlsLoadP") ||289! strncmp(_ident,"tlsLoadP_",9)) ) {290return 1;291}292293if (_matrule != NULL && _insencode != NULL) {294const char* opType = _matrule->_opType;295if (strcmp(opType, "Set")==0)296opType = _matrule->_rChild->_opType;297if (strcmp(opType,"ThreadLocal")==0) {298fprintf(stderr, "Warning: ThreadLocal instruction %s should be named 'tlsLoadP_*'\n",299(_ident == NULL ? "NULL" : _ident));300return 1;301}302}303304return 0;305}306307308// Return 'true' if this instruction matches an ideal 'If' node309bool InstructForm::is_ideal_if() const {310if( _matrule == NULL ) return false;311312return _matrule->is_ideal_if();313}314315// Return 'true' if this instruction matches an ideal 'FastLock' node316bool InstructForm::is_ideal_fastlock() const {317if( _matrule == NULL ) return false;318319return _matrule->is_ideal_fastlock();320}321322// Return 'true' if this instruction matches an ideal 'MemBarXXX' node323bool InstructForm::is_ideal_membar() const {324if( _matrule == NULL ) return false;325326return _matrule->is_ideal_membar();327}328329// Return 'true' if this instruction matches an ideal 'LoadPC' node330bool InstructForm::is_ideal_loadPC() const {331if( _matrule == NULL ) return false;332333return _matrule->is_ideal_loadPC();334}335336// Return 'true' if this instruction matches an ideal 'Box' node337bool InstructForm::is_ideal_box() const {338if( _matrule == NULL ) return false;339340return _matrule->is_ideal_box();341}342343// Return 'true' if this instruction matches an ideal 'Goto' node344bool InstructForm::is_ideal_goto() const {345if( _matrule == NULL ) return false;346347return _matrule->is_ideal_goto();348}349350// Return 'true' if this instruction matches an ideal 'Jump' node351bool InstructForm::is_ideal_jump() const {352if( _matrule == NULL ) return false;353354return _matrule->is_ideal_jump();355}356357// Return 'true' if instruction matches ideal 'If' | 'Goto' | 'CountedLoopEnd'358bool InstructForm::is_ideal_branch() const {359if( _matrule == NULL ) return false;360361return _matrule->is_ideal_if() || _matrule->is_ideal_goto();362}363364365// Return 'true' if this instruction matches an ideal 'Return' node366bool InstructForm::is_ideal_return() const {367if( _matrule == NULL ) return false;368369// Check MatchRule to see if the first entry is the ideal "Return" node370int index = 0;371if (_matrule->find_type("Return",index)) return true;372if (_matrule->find_type("Rethrow",index)) return true;373if (_matrule->find_type("TailCall",index)) return true;374if (_matrule->find_type("TailJump",index)) return true;375376return false;377}378379// Return 'true' if this instruction matches an ideal 'Halt' node380bool InstructForm::is_ideal_halt() const {381int index = 0;382return _matrule && _matrule->find_type("Halt",index);383}384385// Return 'true' if this instruction matches an ideal 'SafePoint' node386bool InstructForm::is_ideal_safepoint() const {387int index = 0;388return _matrule && _matrule->find_type("SafePoint",index);389}390391// Return 'true' if this instruction matches an ideal 'Nop' node392bool InstructForm::is_ideal_nop() const {393return _ident && _ident[0] == 'N' && _ident[1] == 'o' && _ident[2] == 'p' && _ident[3] == '_';394}395396bool InstructForm::is_ideal_control() const {397if ( ! _matrule) return false;398399return is_ideal_return() || is_ideal_branch() || _matrule->is_ideal_jump() || is_ideal_halt();400}401402// Return 'true' if this instruction matches an ideal 'Call' node403Form::CallType InstructForm::is_ideal_call() const {404if( _matrule == NULL ) return Form::invalid_type;405406// Check MatchRule to see if the first entry is the ideal "Call" node407int idx = 0;408if(_matrule->find_type("CallStaticJava",idx)) return Form::JAVA_STATIC;409idx = 0;410if(_matrule->find_type("Lock",idx)) return Form::JAVA_STATIC;411idx = 0;412if(_matrule->find_type("Unlock",idx)) return Form::JAVA_STATIC;413idx = 0;414if(_matrule->find_type("CallDynamicJava",idx)) return Form::JAVA_DYNAMIC;415idx = 0;416if(_matrule->find_type("CallRuntime",idx)) return Form::JAVA_RUNTIME;417idx = 0;418if(_matrule->find_type("CallLeaf",idx)) return Form::JAVA_LEAF;419idx = 0;420if(_matrule->find_type("CallLeafNoFP",idx)) return Form::JAVA_LEAF;421idx = 0;422423return Form::invalid_type;424}425426// Return 'true' if this instruction matches an ideal 'Load?' node427Form::DataType InstructForm::is_ideal_load() const {428if( _matrule == NULL ) return Form::none;429430return _matrule->is_ideal_load();431}432433// Return 'true' if this instruction matches an ideal 'LoadKlass' node434bool InstructForm::skip_antidep_check() const {435if( _matrule == NULL ) return false;436437return _matrule->skip_antidep_check();438}439440// Return 'true' if this instruction matches an ideal 'Load?' node441Form::DataType InstructForm::is_ideal_store() const {442if( _matrule == NULL ) return Form::none;443444return _matrule->is_ideal_store();445}446447// Return 'true' if this instruction matches an ideal vector node448bool InstructForm::is_vector() const {449if( _matrule == NULL ) return false;450451return _matrule->is_vector();452}453454455// Return the input register that must match the output register456// If this is not required, return 0457uint InstructForm::two_address(FormDict &globals) {458uint matching_input = 0;459if(_components.count() == 0) return 0;460461_components.reset();462Component *comp = _components.iter();463// Check if there is a DEF464if( comp->isa(Component::DEF) ) {465// Check that this is a register466const char *def_type = comp->_type;467const Form *form = globals[def_type];468OperandForm *op = form->is_operand();469if( op ) {470if( op->constrained_reg_class() != NULL &&471op->interface_type(globals) == Form::register_interface ) {472// Remember the local name for equality test later473const char *def_name = comp->_name;474// Check if a component has the same name and is a USE475do {476if( comp->isa(Component::USE) && strcmp(comp->_name,def_name)==0 ) {477return operand_position_format(def_name);478}479} while( (comp = _components.iter()) != NULL);480}481}482}483484return 0;485}486487488// when chaining a constant to an instruction, returns 'true' and sets opType489Form::DataType InstructForm::is_chain_of_constant(FormDict &globals) {490const char *dummy = NULL;491const char *dummy2 = NULL;492return is_chain_of_constant(globals, dummy, dummy2);493}494Form::DataType InstructForm::is_chain_of_constant(FormDict &globals,495const char * &opTypeParam) {496const char *result = NULL;497498return is_chain_of_constant(globals, opTypeParam, result);499}500501Form::DataType InstructForm::is_chain_of_constant(FormDict &globals,502const char * &opTypeParam, const char * &resultParam) {503Form::DataType data_type = Form::none;504if ( ! _matrule) return data_type;505506// !!!!!507// The source of the chain rule is 'position = 1'508uint position = 1;509const char *result = NULL;510const char *name = NULL;511const char *opType = NULL;512// Here base_operand is looking for an ideal type to be returned (opType).513if ( _matrule->is_chain_rule(globals)514&& _matrule->base_operand(position, globals, result, name, opType) ) {515data_type = ideal_to_const_type(opType);516517// if it isn't an ideal constant type, just return518if ( data_type == Form::none ) return data_type;519520// Ideal constant types also adjust the opType parameter.521resultParam = result;522opTypeParam = opType;523return data_type;524}525526return data_type;527}528529// Check if a simple chain rule530bool InstructForm::is_simple_chain_rule(FormDict &globals) const {531if( _matrule && _matrule->sets_result()532&& _matrule->_rChild->_lChild == NULL533&& globals[_matrule->_rChild->_opType]534&& globals[_matrule->_rChild->_opType]->is_opclass() ) {535return true;536}537return false;538}539540// check for structural rematerialization541bool InstructForm::rematerialize(FormDict &globals, RegisterForm *registers ) {542bool rematerialize = false;543544Form::DataType data_type = is_chain_of_constant(globals);545if( data_type != Form::none )546rematerialize = true;547548// Constants549if( _components.count() == 1 && _components[0]->is(Component::USE_DEF) )550rematerialize = true;551552// Pseudo-constants (values easily available to the runtime)553if (is_empty_encoding() && is_tls_instruction())554rematerialize = true;555556// 1-input, 1-output, such as copies or increments.557if( _components.count() == 2 &&558_components[0]->is(Component::DEF) &&559_components[1]->isa(Component::USE) )560rematerialize = true;561562// Check for an ideal 'Load?' and eliminate rematerialize option563if ( is_ideal_load() != Form::none || // Ideal load? Do not rematerialize564is_ideal_copy() != Form::none || // Ideal copy? Do not rematerialize565is_expensive() != Form::none) { // Expensive? Do not rematerialize566rematerialize = false;567}568569// Always rematerialize the flags. They are more expensive to save &570// restore than to recompute (and possibly spill the compare's inputs).571if( _components.count() >= 1 ) {572Component *c = _components[0];573const Form *form = globals[c->_type];574OperandForm *opform = form->is_operand();575if( opform ) {576// Avoid the special stack_slots register classes577const char *rc_name = opform->constrained_reg_class();578if( rc_name ) {579if( strcmp(rc_name,"stack_slots") ) {580// Check for ideal_type of RegFlags581const char *type = opform->ideal_type( globals, registers );582if( (type != NULL) && !strcmp(type, "RegFlags") )583rematerialize = true;584} else585rematerialize = false; // Do not rematerialize things target stk586}587}588}589590return rematerialize;591}592593// loads from memory, so must check for anti-dependence594bool InstructForm::needs_anti_dependence_check(FormDict &globals) const {595if ( skip_antidep_check() ) return false;596597// Machine independent loads must be checked for anti-dependences598if( is_ideal_load() != Form::none ) return true;599600// !!!!! !!!!! !!!!!601// TEMPORARY602// if( is_simple_chain_rule(globals) ) return false;603604// String.(compareTo/equals/indexOf) and Arrays.equals use many memorys edges,605// but writes none606if( _matrule && _matrule->_rChild &&607( strcmp(_matrule->_rChild->_opType,"StrComp" )==0 ||608strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 ||609strcmp(_matrule->_rChild->_opType,"StrIndexOf" )==0 ||610strcmp(_matrule->_rChild->_opType,"AryEq" )==0 ))611return true;612613// Check if instruction has a USE of a memory operand class, but no defs614bool USE_of_memory = false;615bool DEF_of_memory = false;616Component *comp = NULL;617ComponentList &components = (ComponentList &)_components;618619components.reset();620while( (comp = components.iter()) != NULL ) {621const Form *form = globals[comp->_type];622if( !form ) continue;623OpClassForm *op = form->is_opclass();624if( !op ) continue;625if( form->interface_type(globals) == Form::memory_interface ) {626if( comp->isa(Component::USE) ) USE_of_memory = true;627if( comp->isa(Component::DEF) ) {628OperandForm *oper = form->is_operand();629if( oper && oper->is_user_name_for_sReg() ) {630// Stack slots are unaliased memory handled by allocator631oper = oper; // debug stopping point !!!!!632} else {633DEF_of_memory = true;634}635}636}637}638return (USE_of_memory && !DEF_of_memory);639}640641642int InstructForm::memory_operand(FormDict &globals) const {643// Machine independent loads must be checked for anti-dependences644// Check if instruction has a USE of a memory operand class, or a def.645int USE_of_memory = 0;646int DEF_of_memory = 0;647const char* last_memory_DEF = NULL; // to test DEF/USE pairing in asserts648const char* last_memory_USE = NULL;649Component *unique = NULL;650Component *comp = NULL;651ComponentList &components = (ComponentList &)_components;652653components.reset();654while( (comp = components.iter()) != NULL ) {655const Form *form = globals[comp->_type];656if( !form ) continue;657OpClassForm *op = form->is_opclass();658if( !op ) continue;659if( op->stack_slots_only(globals) ) continue;660if( form->interface_type(globals) == Form::memory_interface ) {661if( comp->isa(Component::DEF) ) {662last_memory_DEF = comp->_name;663DEF_of_memory++;664unique = comp;665} else if( comp->isa(Component::USE) ) {666if( last_memory_DEF != NULL ) {667assert(0 == strcmp(last_memory_DEF, comp->_name), "every memory DEF is followed by a USE of the same name");668last_memory_DEF = NULL;669}670// Handles same memory being used multiple times in the case of BMI1 instructions.671if (last_memory_USE != NULL) {672if (strcmp(comp->_name, last_memory_USE) != 0) {673USE_of_memory++;674}675} else {676USE_of_memory++;677}678last_memory_USE = comp->_name;679680if (DEF_of_memory == 0) // defs take precedence681unique = comp;682} else {683assert(last_memory_DEF == NULL, "unpaired memory DEF");684}685}686}687assert(last_memory_DEF == NULL, "unpaired memory DEF");688assert(USE_of_memory >= DEF_of_memory, "unpaired memory DEF");689USE_of_memory -= DEF_of_memory; // treat paired DEF/USE as one occurrence690if( (USE_of_memory + DEF_of_memory) > 0 ) {691if( is_simple_chain_rule(globals) ) {692//fprintf(stderr, "Warning: chain rule is not really a memory user.\n");693//((InstructForm*)this)->dump();694// Preceding code prints nothing on sparc and these insns on intel:695// leaP8 leaP32 leaPIdxOff leaPIdxScale leaPIdxScaleOff leaP8 leaP32696// leaPIdxOff leaPIdxScale leaPIdxScaleOff697return NO_MEMORY_OPERAND;698}699700if( DEF_of_memory == 1 ) {701assert(unique != NULL, "");702if( USE_of_memory == 0 ) {703// unique def, no uses704} else {705// // unique def, some uses706// // must return bottom unless all uses match def707// unique = NULL;708}709} else if( DEF_of_memory > 0 ) {710// multiple defs, don't care about uses711unique = NULL;712} else if( USE_of_memory == 1) {713// unique use, no defs714assert(unique != NULL, "");715} else if( USE_of_memory > 0 ) {716// multiple uses, no defs717unique = NULL;718} else {719assert(false, "bad case analysis");720}721// process the unique DEF or USE, if there is one722if( unique == NULL ) {723return MANY_MEMORY_OPERANDS;724} else {725int pos = components.operand_position(unique->_name);726if( unique->isa(Component::DEF) ) {727pos += 1; // get corresponding USE from DEF728}729assert(pos >= 1, "I was just looking at it!");730return pos;731}732}733734// missed the memory op??735if( true ) { // %%% should not be necessary736if( is_ideal_store() != Form::none ) {737fprintf(stderr, "Warning: cannot find memory opnd in instr.\n");738((InstructForm*)this)->dump();739// pretend it has multiple defs and uses740return MANY_MEMORY_OPERANDS;741}742if( is_ideal_load() != Form::none ) {743fprintf(stderr, "Warning: cannot find memory opnd in instr.\n");744((InstructForm*)this)->dump();745// pretend it has multiple uses and no defs746return MANY_MEMORY_OPERANDS;747}748}749750return NO_MEMORY_OPERAND;751}752753754// This instruction captures the machine-independent bottom_type755// Expected use is for pointer vs oop determination for LoadP756bool InstructForm::captures_bottom_type(FormDict &globals) const {757if( _matrule && _matrule->_rChild &&758(!strcmp(_matrule->_rChild->_opType,"CastPP") || // new result type759!strcmp(_matrule->_rChild->_opType,"CastX2P") || // new result type760!strcmp(_matrule->_rChild->_opType,"DecodeN") ||761!strcmp(_matrule->_rChild->_opType,"EncodeP") ||762!strcmp(_matrule->_rChild->_opType,"DecodeNKlass") ||763!strcmp(_matrule->_rChild->_opType,"EncodePKlass") ||764!strcmp(_matrule->_rChild->_opType,"LoadN") ||765!strcmp(_matrule->_rChild->_opType,"LoadNKlass") ||766!strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception767!strcmp(_matrule->_rChild->_opType,"CheckCastPP") ||768!strcmp(_matrule->_rChild->_opType,"GetAndSetP") ||769!strcmp(_matrule->_rChild->_opType,"GetAndSetN")) ) return true;770else if ( is_ideal_load() == Form::idealP ) return true;771else if ( is_ideal_store() != Form::none ) return true;772773if (needs_base_oop_edge(globals)) return true;774775if (is_vector()) return true;776if (is_mach_constant()) return true;777778return false;779}780781782// Access instr_cost attribute or return NULL.783const char* InstructForm::cost() {784for (Attribute* cur = _attribs; cur != NULL; cur = (Attribute*)cur->_next) {785if( strcmp(cur->_ident,AttributeForm::_ins_cost) == 0 ) {786return cur->_val;787}788}789return NULL;790}791792// Return count of top-level operands.793uint InstructForm::num_opnds() {794int num_opnds = _components.num_operands();795796// Need special handling for matching some ideal nodes797// i.e. Matching a return node798/*799if( _matrule ) {800if( strcmp(_matrule->_opType,"Return" )==0 ||801strcmp(_matrule->_opType,"Halt" )==0 )802return 3;803}804*/805return num_opnds;806}807808const char* InstructForm::opnd_ident(int idx) {809return _components.at(idx)->_name;810}811812const char* InstructForm::unique_opnd_ident(uint idx) {813uint i;814for (i = 1; i < num_opnds(); ++i) {815if (unique_opnds_idx(i) == idx) {816break;817}818}819return (_components.at(i) != NULL) ? _components.at(i)->_name : "";820}821822// Return count of unmatched operands.823uint InstructForm::num_post_match_opnds() {824uint num_post_match_opnds = _components.count();825uint num_match_opnds = _components.match_count();826num_post_match_opnds = num_post_match_opnds - num_match_opnds;827828return num_post_match_opnds;829}830831// Return the number of leaves below this complex operand832uint InstructForm::num_consts(FormDict &globals) const {833if ( ! _matrule) return 0;834835// This is a recursive invocation on all operands in the matchrule836return _matrule->num_consts(globals);837}838839// Constants in match rule with specified type840uint InstructForm::num_consts(FormDict &globals, Form::DataType type) const {841if ( ! _matrule) return 0;842843// This is a recursive invocation on all operands in the matchrule844return _matrule->num_consts(globals, type);845}846847848// Return the register class associated with 'leaf'.849const char *InstructForm::out_reg_class(FormDict &globals) {850assert( false, "InstructForm::out_reg_class(FormDict &globals); Not Implemented");851852return NULL;853}854855856857// Lookup the starting position of inputs we are interested in wrt. ideal nodes858uint InstructForm::oper_input_base(FormDict &globals) {859if( !_matrule ) return 1; // Skip control for most nodes860861// Need special handling for matching some ideal nodes862// i.e. Matching a return node863if( strcmp(_matrule->_opType,"Return" )==0 ||864strcmp(_matrule->_opType,"Rethrow" )==0 ||865strcmp(_matrule->_opType,"TailCall" )==0 ||866strcmp(_matrule->_opType,"TailJump" )==0 ||867strcmp(_matrule->_opType,"SafePoint" )==0 ||868strcmp(_matrule->_opType,"Halt" )==0 )869return AdlcVMDeps::Parms; // Skip the machine-state edges870871if( _matrule->_rChild &&872( strcmp(_matrule->_rChild->_opType,"AryEq" )==0 ||873strcmp(_matrule->_rChild->_opType,"StrComp" )==0 ||874strcmp(_matrule->_rChild->_opType,"StrEquals" )==0 ||875strcmp(_matrule->_rChild->_opType,"StrIndexOf")==0 ||876strcmp(_matrule->_rChild->_opType,"EncodeISOArray")==0)) {877// String.(compareTo/equals/indexOf) and Arrays.equals878// and sun.nio.cs.iso8859_1$Encoder.EncodeISOArray879// take 1 control and 1 memory edges.880return 2;881}882883// Check for handling of 'Memory' input/edge in the ideal world.884// The AD file writer is shielded from knowledge of these edges.885int base = 1; // Skip control886base += _matrule->needs_ideal_memory_edge(globals);887888// Also skip the base-oop value for uses of derived oops.889// The AD file writer is shielded from knowledge of these edges.890base += needs_base_oop_edge(globals);891892return base;893}894895// This function determines the order of the MachOper in _opnds[]896// by writing the operand names into the _components list.897//898// Implementation does not modify state of internal structures899void InstructForm::build_components() {900// Add top-level operands to the components901if (_matrule) _matrule->append_components(_localNames, _components);902903// Add parameters that "do not appear in match rule".904bool has_temp = false;905const char *name;906const char *kill_name = NULL;907for (_parameters.reset(); (name = _parameters.iter()) != NULL;) {908OpClassForm *opForm = _localNames[name]->is_opclass();909assert(opForm != NULL, "sanity");910911Effect* e = NULL;912{913const Form* form = _effects[name];914e = form ? form->is_effect() : NULL;915}916917if (e != NULL) {918has_temp |= e->is(Component::TEMP);919920// KILLs must be declared after any TEMPs because TEMPs are real921// uses so their operand numbering must directly follow the real922// inputs from the match rule. Fixing the numbering seems923// complex so simply enforce the restriction during parse.924if (kill_name != NULL &&925e->isa(Component::TEMP) && !e->isa(Component::DEF)) {926OpClassForm* kill = _localNames[kill_name]->is_opclass();927assert(kill != NULL, "sanity");928globalAD->syntax_err(_linenum, "%s: %s %s must be at the end of the argument list\n",929_ident, kill->_ident, kill_name);930} else if (e->isa(Component::KILL) && !e->isa(Component::USE)) {931kill_name = name;932}933}934935const Component *component = _components.search(name);936if ( component == NULL ) {937if (e) {938_components.insert(name, opForm->_ident, e->_use_def, false);939component = _components.search(name);940if (component->isa(Component::USE) && !component->isa(Component::TEMP) && _matrule) {941const Form *form = globalAD->globalNames()[component->_type];942assert( form, "component type must be a defined form");943OperandForm *op = form->is_operand();944if (op->_interface && op->_interface->is_RegInterface()) {945globalAD->syntax_err(_linenum, "%s: illegal USE of non-input: %s %s\n",946_ident, opForm->_ident, name);947}948}949} else {950// This would be a nice warning but it triggers in a few places in a benign way951// if (_matrule != NULL && !expands()) {952// globalAD->syntax_err(_linenum, "%s: %s %s not mentioned in effect or match rule\n",953// _ident, opForm->_ident, name);954// }955_components.insert(name, opForm->_ident, Component::INVALID, false);956}957}958else if (e) {959// Component was found in the list960// Check if there is a new effect that requires an extra component.961// This happens when adding 'USE' to a component that is not yet one.962if ((!component->isa( Component::USE) && ((e->_use_def & Component::USE) != 0))) {963if (component->isa(Component::USE) && _matrule) {964const Form *form = globalAD->globalNames()[component->_type];965assert( form, "component type must be a defined form");966OperandForm *op = form->is_operand();967if (op->_interface && op->_interface->is_RegInterface()) {968globalAD->syntax_err(_linenum, "%s: illegal USE of non-input: %s %s\n",969_ident, opForm->_ident, name);970}971}972_components.insert(name, opForm->_ident, e->_use_def, false);973} else {974Component *comp = (Component*)component;975comp->promote_use_def_info(e->_use_def);976}977// Component positions are zero based.978int pos = _components.operand_position(name);979assert( ! (component->isa(Component::DEF) && (pos >= 1)),980"Component::DEF can only occur in the first position");981}982}983984// Resolving the interactions between expand rules and TEMPs would985// be complex so simply disallow it.986if (_matrule == NULL && has_temp) {987globalAD->syntax_err(_linenum, "%s: TEMPs without match rule isn't supported\n", _ident);988}989990return;991}992993// Return zero-based position in component list; -1 if not in list.994int InstructForm::operand_position(const char *name, int usedef) {995return unique_opnds_idx(_components.operand_position(name, usedef, this));996}997998int InstructForm::operand_position_format(const char *name) {999return unique_opnds_idx(_components.operand_position_format(name, this));1000}10011002// Return zero-based position in component list; -1 if not in list.1003int InstructForm::label_position() {1004return unique_opnds_idx(_components.label_position());1005}10061007int InstructForm::method_position() {1008return unique_opnds_idx(_components.method_position());1009}10101011// Return number of relocation entries needed for this instruction.1012uint InstructForm::reloc(FormDict &globals) {1013uint reloc_entries = 0;1014// Check for "Call" nodes1015if ( is_ideal_call() ) ++reloc_entries;1016if ( is_ideal_return() ) ++reloc_entries;1017if ( is_ideal_safepoint() ) ++reloc_entries;101810191020// Check if operands MAYBE oop pointers, by checking for ConP elements1021// Proceed through the leaves of the match-tree and check for ConPs1022if ( _matrule != NULL ) {1023uint position = 0;1024const char *result = NULL;1025const char *name = NULL;1026const char *opType = NULL;1027while (_matrule->base_operand(position, globals, result, name, opType)) {1028if ( strcmp(opType,"ConP") == 0 ) {1029#ifdef SPARC1030reloc_entries += 2; // 1 for sethi + 1 for setlo1031#else1032++reloc_entries;1033#endif1034}1035++position;1036}1037}10381039// Above is only a conservative estimate1040// because it did not check contents of operand classes.1041// !!!!! !!!!!1042// Add 1 to reloc info for each operand class in the component list.1043Component *comp;1044_components.reset();1045while ( (comp = _components.iter()) != NULL ) {1046const Form *form = globals[comp->_type];1047assert( form, "Did not find component's type in global names");1048const OpClassForm *opc = form->is_opclass();1049const OperandForm *oper = form->is_operand();1050if ( opc && (oper == NULL) ) {1051++reloc_entries;1052} else if ( oper ) {1053// floats and doubles loaded out of method's constant pool require reloc info1054Form::DataType type = oper->is_base_constant(globals);1055if ( (type == Form::idealF) || (type == Form::idealD) ) {1056++reloc_entries;1057}1058}1059}10601061// Float and Double constants may come from the CodeBuffer table1062// and require relocatable addresses for access1063// !!!!!1064// Check for any component being an immediate float or double.1065Form::DataType data_type = is_chain_of_constant(globals);1066if( data_type==idealD || data_type==idealF ) {1067#ifdef SPARC1068// sparc required more relocation entries for floating constants1069// (expires 9/98)1070reloc_entries += 6;1071#else1072reloc_entries++;1073#endif1074}10751076return reloc_entries;1077}10781079// Utility function defined in archDesc.cpp1080extern bool is_def(int usedef);10811082// Return the result of reducing an instruction1083const char *InstructForm::reduce_result() {1084const char* result = "Universe"; // default1085_components.reset();1086Component *comp = _components.iter();1087if (comp != NULL && comp->isa(Component::DEF)) {1088result = comp->_type;1089// Override this if the rule is a store operation:1090if (_matrule && _matrule->_rChild &&1091is_store_to_memory(_matrule->_rChild->_opType))1092result = "Universe";1093}1094return result;1095}10961097// Return the name of the operand on the right hand side of the binary match1098// Return NULL if there is no right hand side1099const char *InstructForm::reduce_right(FormDict &globals) const {1100if( _matrule == NULL ) return NULL;1101return _matrule->reduce_right(globals);1102}11031104// Similar for left1105const char *InstructForm::reduce_left(FormDict &globals) const {1106if( _matrule == NULL ) return NULL;1107return _matrule->reduce_left(globals);1108}110911101111// Base class for this instruction, MachNode except for calls1112const char *InstructForm::mach_base_class(FormDict &globals) const {1113if( is_ideal_call() == Form::JAVA_STATIC ) {1114return "MachCallStaticJavaNode";1115}1116else if( is_ideal_call() == Form::JAVA_DYNAMIC ) {1117return "MachCallDynamicJavaNode";1118}1119else if( is_ideal_call() == Form::JAVA_RUNTIME ) {1120return "MachCallRuntimeNode";1121}1122else if( is_ideal_call() == Form::JAVA_LEAF ) {1123return "MachCallLeafNode";1124}1125else if (is_ideal_return()) {1126return "MachReturnNode";1127}1128else if (is_ideal_halt()) {1129return "MachHaltNode";1130}1131else if (is_ideal_safepoint()) {1132return "MachSafePointNode";1133}1134else if (is_ideal_if()) {1135return "MachIfNode";1136}1137else if (is_ideal_goto()) {1138return "MachGotoNode";1139}1140else if (is_ideal_fastlock()) {1141return "MachFastLockNode";1142}1143else if (is_ideal_nop()) {1144return "MachNopNode";1145}1146else if (is_ideal_membar()) {1147return "MachMemBarNode";1148}1149else if (is_mach_constant()) {1150return "MachConstantNode";1151}1152else if (captures_bottom_type(globals)) {1153return "MachTypeNode";1154} else {1155return "MachNode";1156}1157assert( false, "ShouldNotReachHere()");1158return NULL;1159}11601161// Compare the instruction predicates for textual equality1162bool equivalent_predicates( const InstructForm *instr1, const InstructForm *instr2 ) {1163const Predicate *pred1 = instr1->_predicate;1164const Predicate *pred2 = instr2->_predicate;1165if( pred1 == NULL && pred2 == NULL ) {1166// no predicates means they are identical1167return true;1168}1169if( pred1 != NULL && pred2 != NULL ) {1170// compare the predicates1171if (ADLParser::equivalent_expressions(pred1->_pred, pred2->_pred)) {1172return true;1173}1174}11751176return false;1177}11781179// Check if this instruction can cisc-spill to 'alternate'1180bool InstructForm::cisc_spills_to(ArchDesc &AD, InstructForm *instr) {1181assert( _matrule != NULL && instr->_matrule != NULL, "must have match rules");1182// Do not replace if a cisc-version has been found.1183if( cisc_spill_operand() != Not_cisc_spillable ) return false;11841185int cisc_spill_operand = Maybe_cisc_spillable;1186char *result = NULL;1187char *result2 = NULL;1188const char *op_name = NULL;1189const char *reg_type = NULL;1190FormDict &globals = AD.globalNames();1191cisc_spill_operand = _matrule->matchrule_cisc_spill_match(globals, AD.get_registers(), instr->_matrule, op_name, reg_type);1192if( (cisc_spill_operand != Not_cisc_spillable) && (op_name != NULL) && equivalent_predicates(this, instr) ) {1193cisc_spill_operand = operand_position(op_name, Component::USE);1194int def_oper = operand_position(op_name, Component::DEF);1195if( def_oper == NameList::Not_in_list && instr->num_opnds() == num_opnds()) {1196// Do not support cisc-spilling for destination operands and1197// make sure they have the same number of operands.1198_cisc_spill_alternate = instr;1199instr->set_cisc_alternate(true);1200if( AD._cisc_spill_debug ) {1201fprintf(stderr, "Instruction %s cisc-spills-to %s\n", _ident, instr->_ident);1202fprintf(stderr, " using operand %s %s at index %d\n", reg_type, op_name, cisc_spill_operand);1203}1204// Record that a stack-version of the reg_mask is needed1205// !!!!!1206OperandForm *oper = (OperandForm*)(globals[reg_type]->is_operand());1207assert( oper != NULL, "cisc-spilling non operand");1208const char *reg_class_name = oper->constrained_reg_class();1209AD.set_stack_or_reg(reg_class_name);1210const char *reg_mask_name = AD.reg_mask(*oper);1211set_cisc_reg_mask_name(reg_mask_name);1212const char *stack_or_reg_mask_name = AD.stack_or_reg_mask(*oper);1213} else {1214cisc_spill_operand = Not_cisc_spillable;1215}1216} else {1217cisc_spill_operand = Not_cisc_spillable;1218}12191220set_cisc_spill_operand(cisc_spill_operand);1221return (cisc_spill_operand != Not_cisc_spillable);1222}12231224// Check to see if this instruction can be replaced with the short branch1225// instruction `short-branch'1226bool InstructForm::check_branch_variant(ArchDesc &AD, InstructForm *short_branch) {1227if (_matrule != NULL &&1228this != short_branch && // Don't match myself1229!is_short_branch() && // Don't match another short branch variant1230reduce_result() != NULL &&1231strcmp(reduce_result(), short_branch->reduce_result()) == 0 &&1232_matrule->equivalent(AD.globalNames(), short_branch->_matrule)1233AARCH64_ONLY(&& equivalent_predicates(this, short_branch))) {1234// The instructions are equivalent.12351236// Now verify that both instructions have the same parameters and1237// the same effects. Both branch forms should have the same inputs1238// and resulting projections to correctly replace a long branch node1239// with corresponding short branch node during code generation.12401241bool different = false;1242if (short_branch->_components.count() != _components.count()) {1243different = true;1244} else if (_components.count() > 0) {1245short_branch->_components.reset();1246_components.reset();1247Component *comp;1248while ((comp = _components.iter()) != NULL) {1249Component *short_comp = short_branch->_components.iter();1250if (short_comp == NULL ||1251short_comp->_type != comp->_type ||1252short_comp->_usedef != comp->_usedef) {1253different = true;1254break;1255}1256}1257if (short_branch->_components.iter() != NULL)1258different = true;1259}1260if (different) {1261globalAD->syntax_err(short_branch->_linenum, "Instruction %s and its short form %s have different parameters\n", _ident, short_branch->_ident);1262}1263if (AD._adl_debug > 1 || AD._short_branch_debug) {1264fprintf(stderr, "Instruction %s has short form %s\n", _ident, short_branch->_ident);1265}1266_short_branch_form = short_branch;1267return true;1268}1269return false;1270}127112721273// --------------------------- FILE *output_routines1274//1275// Generate the format call for the replacement variable1276void InstructForm::rep_var_format(FILE *fp, const char *rep_var) {1277// Handle special constant table variables.1278if (strcmp(rep_var, "constanttablebase") == 0) {1279fprintf(fp, "char reg[128]; ra->dump_register(in(mach_constant_base_node_input()), reg);\n");1280fprintf(fp, " st->print(\"%%s\", reg);\n");1281return;1282}1283if (strcmp(rep_var, "constantoffset") == 0) {1284fprintf(fp, "st->print(\"#%%d\", constant_offset_unchecked());\n");1285return;1286}1287if (strcmp(rep_var, "constantaddress") == 0) {1288fprintf(fp, "st->print(\"constant table base + #%%d\", constant_offset_unchecked());\n");1289return;1290}12911292// Find replacement variable's type1293const Form *form = _localNames[rep_var];1294if (form == NULL) {1295globalAD->syntax_err(_linenum, "Unknown replacement variable %s in format statement of %s.",1296rep_var, _ident);1297return;1298}1299OpClassForm *opc = form->is_opclass();1300assert( opc, "replacement variable was not found in local names");1301// Lookup the index position of the replacement variable1302int idx = operand_position_format(rep_var);1303if ( idx == -1 ) {1304globalAD->syntax_err(_linenum, "Could not find replacement variable %s in format statement of %s.\n",1305rep_var, _ident);1306assert(strcmp(opc->_ident, "label") == 0, "Unimplemented");1307return;1308}13091310if (is_noninput_operand(idx)) {1311// This component isn't in the input array. Print out the static1312// name of the register.1313OperandForm* oper = form->is_operand();1314if (oper != NULL && oper->is_bound_register()) {1315const RegDef* first = oper->get_RegClass()->find_first_elem();1316fprintf(fp, " st->print_raw(\"%s\");\n", first->_regname);1317} else {1318globalAD->syntax_err(_linenum, "In %s can't find format for %s %s", _ident, opc->_ident, rep_var);1319}1320} else {1321// Output the format call for this operand1322fprintf(fp,"opnd_array(%d)->",idx);1323if (idx == 0)1324fprintf(fp,"int_format(ra, this, st); // %s\n", rep_var);1325else1326fprintf(fp,"ext_format(ra, this,idx%d, st); // %s\n", idx, rep_var );1327}1328}13291330// Seach through operands to determine parameters unique positions.1331void InstructForm::set_unique_opnds() {1332uint* uniq_idx = NULL;1333uint nopnds = num_opnds();1334uint num_uniq = nopnds;1335uint i;1336_uniq_idx_length = 0;1337if (nopnds > 0) {1338// Allocate index array. Worst case we're mapping from each1339// component back to an index and any DEF always goes at 0 so the1340// length of the array has to be the number of components + 1.1341_uniq_idx_length = _components.count() + 1;1342uniq_idx = (uint*) malloc(sizeof(uint) * _uniq_idx_length);1343for (i = 0; i < _uniq_idx_length; i++) {1344uniq_idx[i] = i;1345}1346}1347// Do it only if there is a match rule and no expand rule. With an1348// expand rule it is done by creating new mach node in Expand()1349// method.1350if (nopnds > 0 && _matrule != NULL && _exprule == NULL) {1351const char *name;1352uint count;1353bool has_dupl_use = false;13541355_parameters.reset();1356while ((name = _parameters.iter()) != NULL) {1357count = 0;1358uint position = 0;1359uint uniq_position = 0;1360_components.reset();1361Component *comp = NULL;1362if (sets_result()) {1363comp = _components.iter();1364position++;1365}1366// The next code is copied from the method operand_position().1367for (; (comp = _components.iter()) != NULL; ++position) {1368// When the first component is not a DEF,1369// leave space for the result operand!1370if (position==0 && (!comp->isa(Component::DEF))) {1371++position;1372}1373if (strcmp(name, comp->_name) == 0) {1374if (++count > 1) {1375assert(position < _uniq_idx_length, "out of bounds");1376uniq_idx[position] = uniq_position;1377has_dupl_use = true;1378} else {1379uniq_position = position;1380}1381}1382if (comp->isa(Component::DEF) && comp->isa(Component::USE)) {1383++position;1384if (position != 1)1385--position; // only use two slots for the 1st USE_DEF1386}1387}1388}1389if (has_dupl_use) {1390for (i = 1; i < nopnds; i++) {1391if (i != uniq_idx[i]) {1392break;1393}1394}1395uint j = i;1396for (; i < nopnds; i++) {1397if (i == uniq_idx[i]) {1398uniq_idx[i] = j++;1399}1400}1401num_uniq = j;1402}1403}1404_uniq_idx = uniq_idx;1405_num_uniq = num_uniq;1406}14071408// Generate index values needed for determining the operand position1409void InstructForm::index_temps(FILE *fp, FormDict &globals, const char *prefix, const char *receiver) {1410uint idx = 0; // position of operand in match rule1411int cur_num_opnds = num_opnds();14121413// Compute the index into vector of operand pointers:1414// idx0=0 is used to indicate that info comes from this same node, not from input edge.1415// idx1 starts at oper_input_base()1416if ( cur_num_opnds >= 1 ) {1417fprintf(fp," // Start at oper_input_base() and count operands\n");1418fprintf(fp," unsigned %sidx0 = %d;\n", prefix, oper_input_base(globals));1419fprintf(fp," unsigned %sidx1 = %d;", prefix, oper_input_base(globals));1420fprintf(fp," \t// %s\n", unique_opnd_ident(1));14211422// Generate starting points for other unique operands if they exist1423for ( idx = 2; idx < num_unique_opnds(); ++idx ) {1424if( *receiver == 0 ) {1425fprintf(fp," unsigned %sidx%d = %sidx%d + opnd_array(%d)->num_edges();",1426prefix, idx, prefix, idx-1, idx-1 );1427} else {1428fprintf(fp," unsigned %sidx%d = %sidx%d + %s_opnds[%d]->num_edges();",1429prefix, idx, prefix, idx-1, receiver, idx-1 );1430}1431fprintf(fp," \t// %s\n", unique_opnd_ident(idx));1432}1433}1434if( *receiver != 0 ) {1435// This value is used by generate_peepreplace when copying a node.1436// Don't emit it in other cases since it can hide bugs with the1437// use invalid idx's.1438fprintf(fp," unsigned %sidx%d = %sreq(); \n", prefix, idx, receiver);1439}14401441}14421443// ---------------------------1444bool InstructForm::verify() {1445// !!!!! !!!!!1446// Check that a "label" operand occurs last in the operand list, if present1447return true;1448}14491450void InstructForm::dump() {1451output(stderr);1452}14531454void InstructForm::output(FILE *fp) {1455fprintf(fp,"\nInstruction: %s\n", (_ident?_ident:""));1456if (_matrule) _matrule->output(fp);1457if (_insencode) _insencode->output(fp);1458if (_constant) _constant->output(fp);1459if (_opcode) _opcode->output(fp);1460if (_attribs) _attribs->output(fp);1461if (_predicate) _predicate->output(fp);1462if (_effects.Size()) {1463fprintf(fp,"Effects\n");1464_effects.dump();1465}1466if (_exprule) _exprule->output(fp);1467if (_rewrule) _rewrule->output(fp);1468if (_format) _format->output(fp);1469if (_peephole) _peephole->output(fp);1470}14711472void MachNodeForm::dump() {1473output(stderr);1474}14751476void MachNodeForm::output(FILE *fp) {1477fprintf(fp,"\nMachNode: %s\n", (_ident?_ident:""));1478}14791480//------------------------------build_predicate--------------------------------1481// Build instruction predicates. If the user uses the same operand name1482// twice, we need to check that the operands are pointer-eequivalent in1483// the DFA during the labeling process.1484Predicate *InstructForm::build_predicate() {1485char buf[1024], *s=buf;1486Dict names(cmpstr,hashstr,Form::arena); // Map Names to counts14871488MatchNode *mnode =1489strcmp(_matrule->_opType, "Set") ? _matrule : _matrule->_rChild;1490mnode->count_instr_names(names);14911492uint first = 1;1493// Start with the predicate supplied in the .ad file.1494if( _predicate ) {1495if( first ) first=0;1496strcpy(s,"("); s += strlen(s);1497strcpy(s,_predicate->_pred);1498s += strlen(s);1499strcpy(s,")"); s += strlen(s);1500}1501for( DictI i(&names); i.test(); ++i ) {1502uintptr_t cnt = (uintptr_t)i._value;1503if( cnt > 1 ) { // Need a predicate at all?1504assert( cnt == 2, "Unimplemented" );1505// Handle many pairs1506if( first ) first=0;1507else { // All tests must pass, so use '&&'1508strcpy(s," && ");1509s += strlen(s);1510}1511// Add predicate to working buffer1512sprintf(s,"/*%s*/(",(char*)i._key);1513s += strlen(s);1514mnode->build_instr_pred(s,(char*)i._key,0);1515s += strlen(s);1516strcpy(s," == "); s += strlen(s);1517mnode->build_instr_pred(s,(char*)i._key,1);1518s += strlen(s);1519strcpy(s,")"); s += strlen(s);1520}1521}1522if( s == buf ) s = NULL;1523else {1524assert( strlen(buf) < sizeof(buf), "String buffer overflow" );1525s = strdup(buf);1526}1527return new Predicate(s);1528}15291530//------------------------------EncodeForm-------------------------------------1531// Constructor1532EncodeForm::EncodeForm()1533: _encClass(cmpstr,hashstr, Form::arena) {1534}1535EncodeForm::~EncodeForm() {1536}15371538// record a new register class1539EncClass *EncodeForm::add_EncClass(const char *className) {1540EncClass *encClass = new EncClass(className);1541_eclasses.addName(className);1542_encClass.Insert(className,encClass);1543return encClass;1544}15451546// Lookup the function body for an encoding class1547EncClass *EncodeForm::encClass(const char *className) {1548assert( className != NULL, "Must provide a defined encoding name");15491550EncClass *encClass = (EncClass*)_encClass[className];1551return encClass;1552}15531554// Lookup the function body for an encoding class1555const char *EncodeForm::encClassBody(const char *className) {1556if( className == NULL ) return NULL;15571558EncClass *encClass = (EncClass*)_encClass[className];1559assert( encClass != NULL, "Encode Class is missing.");1560encClass->_code.reset();1561const char *code = (const char*)encClass->_code.iter();1562assert( code != NULL, "Found an empty encode class body.");15631564return code;1565}15661567// Lookup the function body for an encoding class1568const char *EncodeForm::encClassPrototype(const char *className) {1569assert( className != NULL, "Encode class name must be non NULL.");15701571return className;1572}15731574void EncodeForm::dump() { // Debug printer1575output(stderr);1576}15771578void EncodeForm::output(FILE *fp) { // Write info to output files1579const char *name;1580fprintf(fp,"\n");1581fprintf(fp,"-------------------- Dump EncodeForm --------------------\n");1582for (_eclasses.reset(); (name = _eclasses.iter()) != NULL;) {1583((EncClass*)_encClass[name])->output(fp);1584}1585fprintf(fp,"-------------------- end EncodeForm --------------------\n");1586}1587//------------------------------EncClass---------------------------------------1588EncClass::EncClass(const char *name)1589: _localNames(cmpstr,hashstr, Form::arena), _name(name) {1590}1591EncClass::~EncClass() {1592}15931594// Add a parameter <type,name> pair1595void EncClass::add_parameter(const char *parameter_type, const char *parameter_name) {1596_parameter_type.addName( parameter_type );1597_parameter_name.addName( parameter_name );1598}15991600// Verify operand types in parameter list1601bool EncClass::check_parameter_types(FormDict &globals) {1602// !!!!!1603return false;1604}16051606// Add the decomposed "code" sections of an encoding's code-block1607void EncClass::add_code(const char *code) {1608_code.addName(code);1609}16101611// Add the decomposed "replacement variables" of an encoding's code-block1612void EncClass::add_rep_var(char *replacement_var) {1613_code.addName(NameList::_signal);1614_rep_vars.addName(replacement_var);1615}16161617// Lookup the function body for an encoding class1618int EncClass::rep_var_index(const char *rep_var) {1619uint position = 0;1620const char *name = NULL;16211622_parameter_name.reset();1623while ( (name = _parameter_name.iter()) != NULL ) {1624if ( strcmp(rep_var,name) == 0 ) return position;1625++position;1626}16271628return -1;1629}16301631// Check after parsing1632bool EncClass::verify() {1633// 1!!!!1634// Check that each replacement variable, '$name' in architecture description1635// is actually a local variable for this encode class, or a reserved name1636// "primary, secondary, tertiary"1637return true;1638}16391640void EncClass::dump() {1641output(stderr);1642}16431644// Write info to output files1645void EncClass::output(FILE *fp) {1646fprintf(fp,"EncClass: %s", (_name ? _name : ""));16471648// Output the parameter list1649_parameter_type.reset();1650_parameter_name.reset();1651const char *type = _parameter_type.iter();1652const char *name = _parameter_name.iter();1653fprintf(fp, " ( ");1654for ( ; (type != NULL) && (name != NULL);1655(type = _parameter_type.iter()), (name = _parameter_name.iter()) ) {1656fprintf(fp, " %s %s,", type, name);1657}1658fprintf(fp, " ) ");16591660// Output the code block1661_code.reset();1662_rep_vars.reset();1663const char *code;1664while ( (code = _code.iter()) != NULL ) {1665if ( _code.is_signal(code) ) {1666// A replacement variable1667const char *rep_var = _rep_vars.iter();1668fprintf(fp,"($%s)", rep_var);1669} else {1670// A section of code1671fprintf(fp,"%s", code);1672}1673}16741675}16761677//------------------------------Opcode-----------------------------------------1678Opcode::Opcode(char *primary, char *secondary, char *tertiary)1679: _primary(primary), _secondary(secondary), _tertiary(tertiary) {1680}16811682Opcode::~Opcode() {1683}16841685Opcode::opcode_type Opcode::as_opcode_type(const char *param) {1686if( strcmp(param,"primary") == 0 ) {1687return Opcode::PRIMARY;1688}1689else if( strcmp(param,"secondary") == 0 ) {1690return Opcode::SECONDARY;1691}1692else if( strcmp(param,"tertiary") == 0 ) {1693return Opcode::TERTIARY;1694}1695return Opcode::NOT_AN_OPCODE;1696}16971698bool Opcode::print_opcode(FILE *fp, Opcode::opcode_type desired_opcode) {1699// Default values previously provided by MachNode::primary()...1700const char *description = NULL;1701const char *value = NULL;1702// Check if user provided any opcode definitions1703if( this != NULL ) {1704// Update 'value' if user provided a definition in the instruction1705switch (desired_opcode) {1706case PRIMARY:1707description = "primary()";1708if( _primary != NULL) { value = _primary; }1709break;1710case SECONDARY:1711description = "secondary()";1712if( _secondary != NULL ) { value = _secondary; }1713break;1714case TERTIARY:1715description = "tertiary()";1716if( _tertiary != NULL ) { value = _tertiary; }1717break;1718default:1719assert( false, "ShouldNotReachHere();");1720break;1721}1722}1723if (value != NULL) {1724fprintf(fp, "(%s /*%s*/)", value, description);1725}1726return value != NULL;1727}17281729void Opcode::dump() {1730output(stderr);1731}17321733// Write info to output files1734void Opcode::output(FILE *fp) {1735if (_primary != NULL) fprintf(fp,"Primary opcode: %s\n", _primary);1736if (_secondary != NULL) fprintf(fp,"Secondary opcode: %s\n", _secondary);1737if (_tertiary != NULL) fprintf(fp,"Tertiary opcode: %s\n", _tertiary);1738}17391740//------------------------------InsEncode--------------------------------------1741InsEncode::InsEncode() {1742}1743InsEncode::~InsEncode() {1744}17451746// Add "encode class name" and its parameters1747NameAndList *InsEncode::add_encode(char *encoding) {1748assert( encoding != NULL, "Must provide name for encoding");17491750// add_parameter(NameList::_signal);1751NameAndList *encode = new NameAndList(encoding);1752_encoding.addName((char*)encode);17531754return encode;1755}17561757// Access the list of encodings1758void InsEncode::reset() {1759_encoding.reset();1760// _parameter.reset();1761}1762const char* InsEncode::encode_class_iter() {1763NameAndList *encode_class = (NameAndList*)_encoding.iter();1764return ( encode_class != NULL ? encode_class->name() : NULL );1765}1766// Obtain parameter name from zero based index1767const char *InsEncode::rep_var_name(InstructForm &inst, uint param_no) {1768NameAndList *params = (NameAndList*)_encoding.current();1769assert( params != NULL, "Internal Error");1770const char *param = (*params)[param_no];17711772// Remove '$' if parser placed it there.1773return ( param != NULL && *param == '$') ? (param+1) : param;1774}17751776void InsEncode::dump() {1777output(stderr);1778}17791780// Write info to output files1781void InsEncode::output(FILE *fp) {1782NameAndList *encoding = NULL;1783const char *parameter = NULL;17841785fprintf(fp,"InsEncode: ");1786_encoding.reset();17871788while ( (encoding = (NameAndList*)_encoding.iter()) != 0 ) {1789// Output the encoding being used1790fprintf(fp,"%s(", encoding->name() );17911792// Output its parameter list, if any1793bool first_param = true;1794encoding->reset();1795while ( (parameter = encoding->iter()) != 0 ) {1796// Output the ',' between parameters1797if ( ! first_param ) fprintf(fp,", ");1798first_param = false;1799// Output the parameter1800fprintf(fp,"%s", parameter);1801} // done with parameters1802fprintf(fp,") ");1803} // done with encodings18041805fprintf(fp,"\n");1806}18071808//------------------------------Effect-----------------------------------------1809static int effect_lookup(const char *name) {1810if(!strcmp(name, "USE")) return Component::USE;1811if(!strcmp(name, "DEF")) return Component::DEF;1812if(!strcmp(name, "USE_DEF")) return Component::USE_DEF;1813if(!strcmp(name, "KILL")) return Component::KILL;1814if(!strcmp(name, "USE_KILL")) return Component::USE_KILL;1815if(!strcmp(name, "TEMP")) return Component::TEMP;1816if(!strcmp(name, "INVALID")) return Component::INVALID;1817if(!strcmp(name, "CALL")) return Component::CALL;1818assert( false,"Invalid effect name specified\n");1819return Component::INVALID;1820}18211822const char *Component::getUsedefName() {1823switch (_usedef) {1824case Component::INVALID: return "INVALID"; break;1825case Component::USE: return "USE"; break;1826case Component::USE_DEF: return "USE_DEF"; break;1827case Component::USE_KILL: return "USE_KILL"; break;1828case Component::KILL: return "KILL"; break;1829case Component::TEMP: return "TEMP"; break;1830case Component::DEF: return "DEF"; break;1831case Component::CALL: return "CALL"; break;1832default: assert(false, "unknown effect");1833}1834return "Undefined Use/Def info";1835}18361837Effect::Effect(const char *name) : _name(name), _use_def(effect_lookup(name)) {1838_ftype = Form::EFF;1839}18401841Effect::~Effect() {1842}18431844// Dynamic type check1845Effect *Effect::is_effect() const {1846return (Effect*)this;1847}184818491850// True if this component is equal to the parameter.1851bool Effect::is(int use_def_kill_enum) const {1852return (_use_def == use_def_kill_enum ? true : false);1853}1854// True if this component is used/def'd/kill'd as the parameter suggests.1855bool Effect::isa(int use_def_kill_enum) const {1856return (_use_def & use_def_kill_enum) == use_def_kill_enum;1857}18581859void Effect::dump() {1860output(stderr);1861}18621863void Effect::output(FILE *fp) { // Write info to output files1864fprintf(fp,"Effect: %s\n", (_name?_name:""));1865}18661867//------------------------------ExpandRule-------------------------------------1868ExpandRule::ExpandRule() : _expand_instrs(),1869_newopconst(cmpstr, hashstr, Form::arena) {1870_ftype = Form::EXP;1871}18721873ExpandRule::~ExpandRule() { // Destructor1874}18751876void ExpandRule::add_instruction(NameAndList *instruction_name_and_operand_list) {1877_expand_instrs.addName((char*)instruction_name_and_operand_list);1878}18791880void ExpandRule::reset_instructions() {1881_expand_instrs.reset();1882}18831884NameAndList* ExpandRule::iter_instructions() {1885return (NameAndList*)_expand_instrs.iter();1886}188718881889void ExpandRule::dump() {1890output(stderr);1891}18921893void ExpandRule::output(FILE *fp) { // Write info to output files1894NameAndList *expand_instr = NULL;1895const char *opid = NULL;18961897fprintf(fp,"\nExpand Rule:\n");18981899// Iterate over the instructions 'node' expands into1900for(reset_instructions(); (expand_instr = iter_instructions()) != NULL; ) {1901fprintf(fp,"%s(", expand_instr->name());19021903// iterate over the operand list1904for( expand_instr->reset(); (opid = expand_instr->iter()) != NULL; ) {1905fprintf(fp,"%s ", opid);1906}1907fprintf(fp,");\n");1908}1909}19101911//------------------------------RewriteRule------------------------------------1912RewriteRule::RewriteRule(char* params, char* block)1913: _tempParams(params), _tempBlock(block) { }; // Constructor1914RewriteRule::~RewriteRule() { // Destructor1915}19161917void RewriteRule::dump() {1918output(stderr);1919}19201921void RewriteRule::output(FILE *fp) { // Write info to output files1922fprintf(fp,"\nRewrite Rule:\n%s\n%s\n",1923(_tempParams?_tempParams:""),1924(_tempBlock?_tempBlock:""));1925}192619271928//==============================MachNodes======================================1929//------------------------------MachNodeForm-----------------------------------1930MachNodeForm::MachNodeForm(char *id)1931: _ident(id) {1932}19331934MachNodeForm::~MachNodeForm() {1935}19361937MachNodeForm *MachNodeForm::is_machnode() const {1938return (MachNodeForm*)this;1939}19401941//==============================Operand Classes================================1942//------------------------------OpClassForm------------------------------------1943OpClassForm::OpClassForm(const char* id) : _ident(id) {1944_ftype = Form::OPCLASS;1945}19461947OpClassForm::~OpClassForm() {1948}19491950bool OpClassForm::ideal_only() const { return 0; }19511952OpClassForm *OpClassForm::is_opclass() const {1953return (OpClassForm*)this;1954}19551956Form::InterfaceType OpClassForm::interface_type(FormDict &globals) const {1957if( _oplst.count() == 0 ) return Form::no_interface;19581959// Check that my operands have the same interface type1960Form::InterfaceType interface;1961bool first = true;1962NameList &op_list = (NameList &)_oplst;1963op_list.reset();1964const char *op_name;1965while( (op_name = op_list.iter()) != NULL ) {1966const Form *form = globals[op_name];1967OperandForm *operand = form->is_operand();1968assert( operand, "Entry in operand class that is not an operand");1969if( first ) {1970first = false;1971interface = operand->interface_type(globals);1972} else {1973interface = (interface == operand->interface_type(globals) ? interface : Form::no_interface);1974}1975}1976return interface;1977}19781979bool OpClassForm::stack_slots_only(FormDict &globals) const {1980if( _oplst.count() == 0 ) return false; // how?19811982NameList &op_list = (NameList &)_oplst;1983op_list.reset();1984const char *op_name;1985while( (op_name = op_list.iter()) != NULL ) {1986const Form *form = globals[op_name];1987OperandForm *operand = form->is_operand();1988assert( operand, "Entry in operand class that is not an operand");1989if( !operand->stack_slots_only(globals) ) return false;1990}1991return true;1992}199319941995void OpClassForm::dump() {1996output(stderr);1997}19981999void OpClassForm::output(FILE *fp) {2000const char *name;2001fprintf(fp,"\nOperand Class: %s\n", (_ident?_ident:""));2002fprintf(fp,"\nCount = %d\n", _oplst.count());2003for(_oplst.reset(); (name = _oplst.iter()) != NULL;) {2004fprintf(fp,"%s, ",name);2005}2006fprintf(fp,"\n");2007}200820092010//==============================Operands=======================================2011//------------------------------OperandForm------------------------------------2012OperandForm::OperandForm(const char* id)2013: OpClassForm(id), _ideal_only(false),2014_localNames(cmpstr, hashstr, Form::arena) {2015_ftype = Form::OPER;20162017_matrule = NULL;2018_interface = NULL;2019_attribs = NULL;2020_predicate = NULL;2021_constraint= NULL;2022_construct = NULL;2023_format = NULL;2024}2025OperandForm::OperandForm(const char* id, bool ideal_only)2026: OpClassForm(id), _ideal_only(ideal_only),2027_localNames(cmpstr, hashstr, Form::arena) {2028_ftype = Form::OPER;20292030_matrule = NULL;2031_interface = NULL;2032_attribs = NULL;2033_predicate = NULL;2034_constraint= NULL;2035_construct = NULL;2036_format = NULL;2037}2038OperandForm::~OperandForm() {2039}204020412042OperandForm *OperandForm::is_operand() const {2043return (OperandForm*)this;2044}20452046bool OperandForm::ideal_only() const {2047return _ideal_only;2048}20492050Form::InterfaceType OperandForm::interface_type(FormDict &globals) const {2051if( _interface == NULL ) return Form::no_interface;20522053return _interface->interface_type(globals);2054}205520562057bool OperandForm::stack_slots_only(FormDict &globals) const {2058if( _constraint == NULL ) return false;2059return _constraint->stack_slots_only();2060}206120622063// Access op_cost attribute or return NULL.2064const char* OperandForm::cost() {2065for (Attribute* cur = _attribs; cur != NULL; cur = (Attribute*)cur->_next) {2066if( strcmp(cur->_ident,AttributeForm::_op_cost) == 0 ) {2067return cur->_val;2068}2069}2070return NULL;2071}20722073// Return the number of leaves below this complex operand2074uint OperandForm::num_leaves() const {2075if ( ! _matrule) return 0;20762077int num_leaves = _matrule->_numleaves;2078return num_leaves;2079}20802081// Return the number of constants contained within this complex operand2082uint OperandForm::num_consts(FormDict &globals) const {2083if ( ! _matrule) return 0;20842085// This is a recursive invocation on all operands in the matchrule2086return _matrule->num_consts(globals);2087}20882089// Return the number of constants in match rule with specified type2090uint OperandForm::num_consts(FormDict &globals, Form::DataType type) const {2091if ( ! _matrule) return 0;20922093// This is a recursive invocation on all operands in the matchrule2094return _matrule->num_consts(globals, type);2095}20962097// Return the number of pointer constants contained within this complex operand2098uint OperandForm::num_const_ptrs(FormDict &globals) const {2099if ( ! _matrule) return 0;21002101// This is a recursive invocation on all operands in the matchrule2102return _matrule->num_const_ptrs(globals);2103}21042105uint OperandForm::num_edges(FormDict &globals) const {2106uint edges = 0;2107uint leaves = num_leaves();2108uint consts = num_consts(globals);21092110// If we are matching a constant directly, there are no leaves.2111edges = ( leaves > consts ) ? leaves - consts : 0;21122113// !!!!!2114// Special case operands that do not have a corresponding ideal node.2115if( (edges == 0) && (consts == 0) ) {2116if( constrained_reg_class() != NULL ) {2117edges = 1;2118} else {2119if( _matrule2120&& (_matrule->_lChild == NULL) && (_matrule->_rChild == NULL) ) {2121const Form *form = globals[_matrule->_opType];2122OperandForm *oper = form ? form->is_operand() : NULL;2123if( oper ) {2124return oper->num_edges(globals);2125}2126}2127}2128}21292130return edges;2131}213221332134// Check if this operand is usable for cisc-spilling2135bool OperandForm::is_cisc_reg(FormDict &globals) const {2136const char *ideal = ideal_type(globals);2137bool is_cisc_reg = (ideal && (ideal_to_Reg_type(ideal) != none));2138return is_cisc_reg;2139}21402141bool OpClassForm::is_cisc_mem(FormDict &globals) const {2142Form::InterfaceType my_interface = interface_type(globals);2143return (my_interface == memory_interface);2144}214521462147// node matches ideal 'Bool'2148bool OperandForm::is_ideal_bool() const {2149if( _matrule == NULL ) return false;21502151return _matrule->is_ideal_bool();2152}21532154// Require user's name for an sRegX to be stackSlotX2155Form::DataType OperandForm::is_user_name_for_sReg() const {2156DataType data_type = none;2157if( _ident != NULL ) {2158if( strcmp(_ident,"stackSlotI") == 0 ) data_type = Form::idealI;2159else if( strcmp(_ident,"stackSlotP") == 0 ) data_type = Form::idealP;2160else if( strcmp(_ident,"stackSlotD") == 0 ) data_type = Form::idealD;2161else if( strcmp(_ident,"stackSlotF") == 0 ) data_type = Form::idealF;2162else if( strcmp(_ident,"stackSlotL") == 0 ) data_type = Form::idealL;2163}2164assert((data_type == none) || (_matrule == NULL), "No match-rule for stackSlotX");21652166return data_type;2167}216821692170// Return ideal type, if there is a single ideal type for this operand2171const char *OperandForm::ideal_type(FormDict &globals, RegisterForm *registers) const {2172const char *type = NULL;2173if (ideal_only()) type = _ident;2174else if( _matrule == NULL ) {2175// Check for condition code register2176const char *rc_name = constrained_reg_class();2177// !!!!!2178if (rc_name == NULL) return NULL;2179// !!!!! !!!!!2180// Check constraints on result's register class2181if( registers ) {2182RegClass *reg_class = registers->getRegClass(rc_name);2183assert( reg_class != NULL, "Register class is not defined");21842185// Check for ideal type of entries in register class, all are the same type2186reg_class->reset();2187RegDef *reg_def = reg_class->RegDef_iter();2188assert( reg_def != NULL, "No entries in register class");2189assert( reg_def->_idealtype != NULL, "Did not define ideal type for register");2190// Return substring that names the register's ideal type2191type = reg_def->_idealtype + 3;2192assert( *(reg_def->_idealtype + 0) == 'O', "Expect Op_ prefix");2193assert( *(reg_def->_idealtype + 1) == 'p', "Expect Op_ prefix");2194assert( *(reg_def->_idealtype + 2) == '_', "Expect Op_ prefix");2195}2196}2197else if( _matrule->_lChild == NULL && _matrule->_rChild == NULL ) {2198// This operand matches a single type, at the top level.2199// Check for ideal type2200type = _matrule->_opType;2201if( strcmp(type,"Bool") == 0 )2202return "Bool";2203// transitive lookup2204const Form *frm = globals[type];2205OperandForm *op = frm->is_operand();2206type = op->ideal_type(globals, registers);2207}2208return type;2209}221022112212// If there is a single ideal type for this interface field, return it.2213const char *OperandForm::interface_ideal_type(FormDict &globals,2214const char *field) const {2215const char *ideal_type = NULL;2216const char *value = NULL;22172218// Check if "field" is valid for this operand's interface2219if ( ! is_interface_field(field, value) ) return ideal_type;22202221// !!!!! !!!!! !!!!!2222// If a valid field has a constant value, identify "ConI" or "ConP" or ...22232224// Else, lookup type of field's replacement variable22252226return ideal_type;2227}222822292230RegClass* OperandForm::get_RegClass() const {2231if (_interface && !_interface->is_RegInterface()) return NULL;2232return globalAD->get_registers()->getRegClass(constrained_reg_class());2233}223422352236bool OperandForm::is_bound_register() const {2237RegClass* reg_class = get_RegClass();2238if (reg_class == NULL) {2239return false;2240}22412242const char* name = ideal_type(globalAD->globalNames());2243if (name == NULL) {2244return false;2245}22462247uint size = 0;2248if (strcmp(name, "RegFlags") == 0) size = 1;2249if (strcmp(name, "RegI") == 0) size = 1;2250if (strcmp(name, "RegF") == 0) size = 1;2251if (strcmp(name, "RegD") == 0) size = 2;2252if (strcmp(name, "RegL") == 0) size = 2;2253if (strcmp(name, "RegN") == 0) size = 1;2254if (strcmp(name, "RegP") == 0) size = globalAD->get_preproc_def("_LP64") ? 2 : 1;2255if (size == 0) {2256return false;2257}2258return size == reg_class->size();2259}226022612262// Check if this is a valid field for this operand,2263// Return 'true' if valid, and set the value to the string the user provided.2264bool OperandForm::is_interface_field(const char *field,2265const char * &value) const {2266return false;2267}226822692270// Return register class name if a constraint specifies the register class.2271const char *OperandForm::constrained_reg_class() const {2272const char *reg_class = NULL;2273if ( _constraint ) {2274// !!!!!2275Constraint *constraint = _constraint;2276if ( strcmp(_constraint->_func,"ALLOC_IN_RC") == 0 ) {2277reg_class = _constraint->_arg;2278}2279}22802281return reg_class;2282}228322842285// Return the register class associated with 'leaf'.2286const char *OperandForm::in_reg_class(uint leaf, FormDict &globals) {2287const char *reg_class = NULL; // "RegMask::Empty";22882289if((_matrule == NULL) || (_matrule->is_chain_rule(globals))) {2290reg_class = constrained_reg_class();2291return reg_class;2292}2293const char *result = NULL;2294const char *name = NULL;2295const char *type = NULL;2296// iterate through all base operands2297// until we reach the register that corresponds to "leaf"2298// This function is not looking for an ideal type. It needs the first2299// level user type associated with the leaf.2300for(uint idx = 0;_matrule->base_operand(idx,globals,result,name,type);++idx) {2301const Form *form = (_localNames[name] ? _localNames[name] : globals[result]);2302OperandForm *oper = form ? form->is_operand() : NULL;2303if( oper ) {2304reg_class = oper->constrained_reg_class();2305if( reg_class ) {2306reg_class = reg_class;2307} else {2308// ShouldNotReachHere();2309}2310} else {2311// ShouldNotReachHere();2312}23132314// Increment our target leaf position if current leaf is not a candidate.2315if( reg_class == NULL) ++leaf;2316// Exit the loop with the value of reg_class when at the correct index2317if( idx == leaf ) break;2318// May iterate through all base operands if reg_class for 'leaf' is NULL2319}2320return reg_class;2321}232223232324// Recursive call to construct list of top-level operands.2325// Implementation does not modify state of internal structures2326void OperandForm::build_components() {2327if (_matrule) _matrule->append_components(_localNames, _components);23282329// Add parameters that "do not appear in match rule".2330const char *name;2331for (_parameters.reset(); (name = _parameters.iter()) != NULL;) {2332OpClassForm *opForm = _localNames[name]->is_opclass();2333assert(opForm != NULL, "sanity");23342335if ( _components.operand_position(name) == -1 ) {2336_components.insert(name, opForm->_ident, Component::INVALID, false);2337}2338}23392340return;2341}23422343int OperandForm::operand_position(const char *name, int usedef) {2344return _components.operand_position(name, usedef, this);2345}234623472348// Return zero-based position in component list, only counting constants;2349// Return -1 if not in list.2350int OperandForm::constant_position(FormDict &globals, const Component *last) {2351// Iterate through components and count constants preceding 'constant'2352int position = 0;2353Component *comp;2354_components.reset();2355while( (comp = _components.iter()) != NULL && (comp != last) ) {2356// Special case for operands that take a single user-defined operand2357// Skip the initial definition in the component list.2358if( strcmp(comp->_name,this->_ident) == 0 ) continue;23592360const char *type = comp->_type;2361// Lookup operand form for replacement variable's type2362const Form *form = globals[type];2363assert( form != NULL, "Component's type not found");2364OperandForm *oper = form ? form->is_operand() : NULL;2365if( oper ) {2366if( oper->_matrule->is_base_constant(globals) != Form::none ) {2367++position;2368}2369}2370}23712372// Check for being passed a component that was not in the list2373if( comp != last ) position = -1;23742375return position;2376}2377// Provide position of constant by "name"2378int OperandForm::constant_position(FormDict &globals, const char *name) {2379const Component *comp = _components.search(name);2380int idx = constant_position( globals, comp );23812382return idx;2383}238423852386// Return zero-based position in component list, only counting constants;2387// Return -1 if not in list.2388int OperandForm::register_position(FormDict &globals, const char *reg_name) {2389// Iterate through components and count registers preceding 'last'2390uint position = 0;2391Component *comp;2392_components.reset();2393while( (comp = _components.iter()) != NULL2394&& (strcmp(comp->_name,reg_name) != 0) ) {2395// Special case for operands that take a single user-defined operand2396// Skip the initial definition in the component list.2397if( strcmp(comp->_name,this->_ident) == 0 ) continue;23982399const char *type = comp->_type;2400// Lookup operand form for component's type2401const Form *form = globals[type];2402assert( form != NULL, "Component's type not found");2403OperandForm *oper = form ? form->is_operand() : NULL;2404if( oper ) {2405if( oper->_matrule->is_base_register(globals) ) {2406++position;2407}2408}2409}24102411return position;2412}241324142415const char *OperandForm::reduce_result() const {2416return _ident;2417}2418// Return the name of the operand on the right hand side of the binary match2419// Return NULL if there is no right hand side2420const char *OperandForm::reduce_right(FormDict &globals) const {2421return ( _matrule ? _matrule->reduce_right(globals) : NULL );2422}24232424// Similar for left2425const char *OperandForm::reduce_left(FormDict &globals) const {2426return ( _matrule ? _matrule->reduce_left(globals) : NULL );2427}242824292430// --------------------------- FILE *output_routines2431//2432// Output code for disp_is_oop, if true.2433void OperandForm::disp_is_oop(FILE *fp, FormDict &globals) {2434// Check it is a memory interface with a non-user-constant disp field2435if ( this->_interface == NULL ) return;2436MemInterface *mem_interface = this->_interface->is_MemInterface();2437if ( mem_interface == NULL ) return;2438const char *disp = mem_interface->_disp;2439if ( *disp != '$' ) return;24402441// Lookup replacement variable in operand's component list2442const char *rep_var = disp + 1;2443const Component *comp = this->_components.search(rep_var);2444assert( comp != NULL, "Replacement variable not found in components");2445// Lookup operand form for replacement variable's type2446const char *type = comp->_type;2447Form *form = (Form*)globals[type];2448assert( form != NULL, "Replacement variable's type not found");2449OperandForm *op = form->is_operand();2450assert( op, "Memory Interface 'disp' can only emit an operand form");2451// Check if this is a ConP, which may require relocation2452if ( op->is_base_constant(globals) == Form::idealP ) {2453// Find the constant's index: _c0, _c1, _c2, ... , _cN2454uint idx = op->constant_position( globals, rep_var);2455fprintf(fp," virtual relocInfo::relocType disp_reloc() const {");2456fprintf(fp, " return _c%d->reloc();", idx);2457fprintf(fp, " }\n");2458}2459}24602461// Generate code for internal and external format methods2462//2463// internal access to reg# node->_idx2464// access to subsumed constant _c0, _c1,2465void OperandForm::int_format(FILE *fp, FormDict &globals, uint index) {2466Form::DataType dtype;2467if (_matrule && (_matrule->is_base_register(globals) ||2468strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) {2469// !!!!! !!!!!2470fprintf(fp," { char reg_str[128];\n");2471fprintf(fp," ra->dump_register(node,reg_str);\n");2472fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');2473fprintf(fp," }\n");2474} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {2475format_constant( fp, index, dtype );2476} else if (ideal_to_sReg_type(_ident) != Form::none) {2477// Special format for Stack Slot Register2478fprintf(fp," { char reg_str[128];\n");2479fprintf(fp," ra->dump_register(node,reg_str);\n");2480fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');2481fprintf(fp," }\n");2482} else {2483fprintf(fp," st->print(\"No format defined for %s\n\");\n", _ident);2484fflush(fp);2485fprintf(stderr,"No format defined for %s\n", _ident);2486dump();2487assert( false,"Internal error:\n output_internal_operand() attempting to output other than a Register or Constant");2488}2489}24902491// Similar to "int_format" but for cases where data is external to operand2492// external access to reg# node->in(idx)->_idx,2493void OperandForm::ext_format(FILE *fp, FormDict &globals, uint index) {2494Form::DataType dtype;2495if (_matrule && (_matrule->is_base_register(globals) ||2496strcmp(ideal_type(globalAD->globalNames()), "RegFlags") == 0)) {2497fprintf(fp," { char reg_str[128];\n");2498fprintf(fp," ra->dump_register(node->in(idx");2499if ( index != 0 ) fprintf(fp, "+%d",index);2500fprintf(fp, "),reg_str);\n");2501fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');2502fprintf(fp," }\n");2503} else if (_matrule && (dtype = _matrule->is_base_constant(globals)) != Form::none) {2504format_constant( fp, index, dtype );2505} else if (ideal_to_sReg_type(_ident) != Form::none) {2506// Special format for Stack Slot Register2507fprintf(fp," { char reg_str[128];\n");2508fprintf(fp," ra->dump_register(node->in(idx");2509if ( index != 0 ) fprintf(fp, "+%d",index);2510fprintf(fp, "),reg_str);\n");2511fprintf(fp," st->print(\"%cs\",reg_str);\n",'%');2512fprintf(fp," }\n");2513} else {2514fprintf(fp," st->print(\"No format defined for %s\n\");\n", _ident);2515assert( false,"Internal error:\n output_external_operand() attempting to output other than a Register or Constant");2516}2517}25182519void OperandForm::format_constant(FILE *fp, uint const_index, uint const_type) {2520switch(const_type) {2521case Form::idealI: fprintf(fp," st->print(\"#%%d\", _c%d);\n", const_index); break;2522case Form::idealP: fprintf(fp," if (_c%d) _c%d->dump_on(st);\n", const_index, const_index); break;2523case Form::idealNKlass:2524case Form::idealN: fprintf(fp," if (_c%d) _c%d->dump_on(st);\n", const_index, const_index); break;2525case Form::idealL: fprintf(fp," st->print(\"#\" INT64_FORMAT, (int64_t)_c%d);\n", const_index); break;2526case Form::idealF: fprintf(fp," st->print(\"#%%f\", _c%d);\n", const_index); break;2527case Form::idealD: fprintf(fp," st->print(\"#%%f\", _c%d);\n", const_index); break;2528default:2529assert( false, "ShouldNotReachHere()");2530}2531}25322533// Return the operand form corresponding to the given index, else NULL.2534OperandForm *OperandForm::constant_operand(FormDict &globals,2535uint index) {2536// !!!!!2537// Check behavior on complex operands2538uint n_consts = num_consts(globals);2539if( n_consts > 0 ) {2540uint i = 0;2541const char *type;2542Component *comp;2543_components.reset();2544if ((comp = _components.iter()) == NULL) {2545assert(n_consts == 1, "Bad component list detected.\n");2546// Current operand is THE operand2547if ( index == 0 ) {2548return this;2549}2550} // end if NULL2551else {2552// Skip the first component, it can not be a DEF of a constant2553do {2554type = comp->base_type(globals);2555// Check that "type" is a 'ConI', 'ConP', ...2556if ( ideal_to_const_type(type) != Form::none ) {2557// When at correct component, get corresponding Operand2558if ( index == 0 ) {2559return globals[comp->_type]->is_operand();2560}2561// Decrement number of constants to go2562--index;2563}2564} while((comp = _components.iter()) != NULL);2565}2566}25672568// Did not find a constant for this index.2569return NULL;2570}25712572// If this operand has a single ideal type, return its type2573Form::DataType OperandForm::simple_type(FormDict &globals) const {2574const char *type_name = ideal_type(globals);2575Form::DataType type = type_name ? ideal_to_const_type( type_name )2576: Form::none;2577return type;2578}25792580Form::DataType OperandForm::is_base_constant(FormDict &globals) const {2581if ( _matrule == NULL ) return Form::none;25822583return _matrule->is_base_constant(globals);2584}25852586// "true" if this operand is a simple type that is swallowed2587bool OperandForm::swallowed(FormDict &globals) const {2588Form::DataType type = simple_type(globals);2589if( type != Form::none ) {2590return true;2591}25922593return false;2594}25952596// Output code to access the value of the index'th constant2597void OperandForm::access_constant(FILE *fp, FormDict &globals,2598uint const_index) {2599OperandForm *oper = constant_operand(globals, const_index);2600assert( oper, "Index exceeds number of constants in operand");2601Form::DataType dtype = oper->is_base_constant(globals);26022603switch(dtype) {2604case idealI: fprintf(fp,"_c%d", const_index); break;2605case idealP: fprintf(fp,"_c%d->get_con()",const_index); break;2606case idealL: fprintf(fp,"_c%d", const_index); break;2607case idealF: fprintf(fp,"_c%d", const_index); break;2608case idealD: fprintf(fp,"_c%d", const_index); break;2609default:2610assert( false, "ShouldNotReachHere()");2611}2612}261326142615void OperandForm::dump() {2616output(stderr);2617}26182619void OperandForm::output(FILE *fp) {2620fprintf(fp,"\nOperand: %s\n", (_ident?_ident:""));2621if (_matrule) _matrule->dump();2622if (_interface) _interface->dump();2623if (_attribs) _attribs->dump();2624if (_predicate) _predicate->dump();2625if (_constraint) _constraint->dump();2626if (_construct) _construct->dump();2627if (_format) _format->dump();2628}26292630//------------------------------Constraint-------------------------------------2631Constraint::Constraint(const char *func, const char *arg)2632: _func(func), _arg(arg) {2633}2634Constraint::~Constraint() { /* not owner of char* */2635}26362637bool Constraint::stack_slots_only() const {2638return strcmp(_func, "ALLOC_IN_RC") == 02639&& strcmp(_arg, "stack_slots") == 0;2640}26412642void Constraint::dump() {2643output(stderr);2644}26452646void Constraint::output(FILE *fp) { // Write info to output files2647assert((_func != NULL && _arg != NULL),"missing constraint function or arg");2648fprintf(fp,"Constraint: %s ( %s )\n", _func, _arg);2649}26502651//------------------------------Predicate--------------------------------------2652Predicate::Predicate(char *pr)2653: _pred(pr) {2654}2655Predicate::~Predicate() {2656}26572658void Predicate::dump() {2659output(stderr);2660}26612662void Predicate::output(FILE *fp) {2663fprintf(fp,"Predicate"); // Write to output files2664}2665//------------------------------Interface--------------------------------------2666Interface::Interface(const char *name) : _name(name) {2667}2668Interface::~Interface() {2669}26702671Form::InterfaceType Interface::interface_type(FormDict &globals) const {2672Interface *thsi = (Interface*)this;2673if ( thsi->is_RegInterface() ) return Form::register_interface;2674if ( thsi->is_MemInterface() ) return Form::memory_interface;2675if ( thsi->is_ConstInterface() ) return Form::constant_interface;2676if ( thsi->is_CondInterface() ) return Form::conditional_interface;26772678return Form::no_interface;2679}26802681RegInterface *Interface::is_RegInterface() {2682if ( strcmp(_name,"REG_INTER") != 0 )2683return NULL;2684return (RegInterface*)this;2685}2686MemInterface *Interface::is_MemInterface() {2687if ( strcmp(_name,"MEMORY_INTER") != 0 ) return NULL;2688return (MemInterface*)this;2689}2690ConstInterface *Interface::is_ConstInterface() {2691if ( strcmp(_name,"CONST_INTER") != 0 ) return NULL;2692return (ConstInterface*)this;2693}2694CondInterface *Interface::is_CondInterface() {2695if ( strcmp(_name,"COND_INTER") != 0 ) return NULL;2696return (CondInterface*)this;2697}269826992700void Interface::dump() {2701output(stderr);2702}27032704// Write info to output files2705void Interface::output(FILE *fp) {2706fprintf(fp,"Interface: %s\n", (_name ? _name : "") );2707}27082709//------------------------------RegInterface-----------------------------------2710RegInterface::RegInterface() : Interface("REG_INTER") {2711}2712RegInterface::~RegInterface() {2713}27142715void RegInterface::dump() {2716output(stderr);2717}27182719// Write info to output files2720void RegInterface::output(FILE *fp) {2721Interface::output(fp);2722}27232724//------------------------------ConstInterface---------------------------------2725ConstInterface::ConstInterface() : Interface("CONST_INTER") {2726}2727ConstInterface::~ConstInterface() {2728}27292730void ConstInterface::dump() {2731output(stderr);2732}27332734// Write info to output files2735void ConstInterface::output(FILE *fp) {2736Interface::output(fp);2737}27382739//------------------------------MemInterface-----------------------------------2740MemInterface::MemInterface(char *base, char *index, char *scale, char *disp)2741: Interface("MEMORY_INTER"), _base(base), _index(index), _scale(scale), _disp(disp) {2742}2743MemInterface::~MemInterface() {2744// not owner of any character arrays2745}27462747void MemInterface::dump() {2748output(stderr);2749}27502751// Write info to output files2752void MemInterface::output(FILE *fp) {2753Interface::output(fp);2754if ( _base != NULL ) fprintf(fp," base == %s\n", _base);2755if ( _index != NULL ) fprintf(fp," index == %s\n", _index);2756if ( _scale != NULL ) fprintf(fp," scale == %s\n", _scale);2757if ( _disp != NULL ) fprintf(fp," disp == %s\n", _disp);2758// fprintf(fp,"\n");2759}27602761//------------------------------CondInterface----------------------------------2762CondInterface::CondInterface(const char* equal, const char* equal_format,2763const char* not_equal, const char* not_equal_format,2764const char* less, const char* less_format,2765const char* greater_equal, const char* greater_equal_format,2766const char* less_equal, const char* less_equal_format,2767const char* greater, const char* greater_format,2768const char* overflow, const char* overflow_format,2769const char* no_overflow, const char* no_overflow_format)2770: Interface("COND_INTER"),2771_equal(equal), _equal_format(equal_format),2772_not_equal(not_equal), _not_equal_format(not_equal_format),2773_less(less), _less_format(less_format),2774_greater_equal(greater_equal), _greater_equal_format(greater_equal_format),2775_less_equal(less_equal), _less_equal_format(less_equal_format),2776_greater(greater), _greater_format(greater_format),2777_overflow(overflow), _overflow_format(overflow_format),2778_no_overflow(no_overflow), _no_overflow_format(no_overflow_format) {2779}2780CondInterface::~CondInterface() {2781// not owner of any character arrays2782}27832784void CondInterface::dump() {2785output(stderr);2786}27872788// Write info to output files2789void CondInterface::output(FILE *fp) {2790Interface::output(fp);2791if ( _equal != NULL ) fprintf(fp," equal == %s\n", _equal);2792if ( _not_equal != NULL ) fprintf(fp," not_equal == %s\n", _not_equal);2793if ( _less != NULL ) fprintf(fp," less == %s\n", _less);2794if ( _greater_equal != NULL ) fprintf(fp," greater_equal == %s\n", _greater_equal);2795if ( _less_equal != NULL ) fprintf(fp," less_equal == %s\n", _less_equal);2796if ( _greater != NULL ) fprintf(fp," greater == %s\n", _greater);2797if ( _overflow != NULL ) fprintf(fp," overflow == %s\n", _overflow);2798if ( _no_overflow != NULL ) fprintf(fp," no_overflow == %s\n", _no_overflow);2799// fprintf(fp,"\n");2800}28012802//------------------------------ConstructRule----------------------------------2803ConstructRule::ConstructRule(char *cnstr)2804: _construct(cnstr) {2805}2806ConstructRule::~ConstructRule() {2807}28082809void ConstructRule::dump() {2810output(stderr);2811}28122813void ConstructRule::output(FILE *fp) {2814fprintf(fp,"\nConstruct Rule\n"); // Write to output files2815}281628172818//==============================Shared Forms===================================2819//------------------------------AttributeForm----------------------------------2820int AttributeForm::_insId = 0; // start counter at 02821int AttributeForm::_opId = 0; // start counter at 02822const char* AttributeForm::_ins_cost = "ins_cost"; // required name2823const char* AttributeForm::_op_cost = "op_cost"; // required name28242825AttributeForm::AttributeForm(char *attr, int type, char *attrdef)2826: Form(Form::ATTR), _attrname(attr), _atype(type), _attrdef(attrdef) {2827if (type==OP_ATTR) {2828id = ++_opId;2829}2830else if (type==INS_ATTR) {2831id = ++_insId;2832}2833else assert( false,"");2834}2835AttributeForm::~AttributeForm() {2836}28372838// Dynamic type check2839AttributeForm *AttributeForm::is_attribute() const {2840return (AttributeForm*)this;2841}284228432844// inlined // int AttributeForm::type() { return id;}28452846void AttributeForm::dump() {2847output(stderr);2848}28492850void AttributeForm::output(FILE *fp) {2851if( _attrname && _attrdef ) {2852fprintf(fp,"\n// AttributeForm \nstatic const int %s = %s;\n",2853_attrname, _attrdef);2854}2855else {2856fprintf(fp,"\n// AttributeForm missing name %s or definition %s\n",2857(_attrname?_attrname:""), (_attrdef?_attrdef:"") );2858}2859}28602861//------------------------------Component--------------------------------------2862Component::Component(const char *name, const char *type, int usedef)2863: _name(name), _type(type), _usedef(usedef) {2864_ftype = Form::COMP;2865}2866Component::~Component() {2867}28682869// True if this component is equal to the parameter.2870bool Component::is(int use_def_kill_enum) const {2871return (_usedef == use_def_kill_enum ? true : false);2872}2873// True if this component is used/def'd/kill'd as the parameter suggests.2874bool Component::isa(int use_def_kill_enum) const {2875return (_usedef & use_def_kill_enum) == use_def_kill_enum;2876}28772878// Extend this component with additional use/def/kill behavior2879int Component::promote_use_def_info(int new_use_def) {2880_usedef |= new_use_def;28812882return _usedef;2883}28842885// Check the base type of this component, if it has one2886const char *Component::base_type(FormDict &globals) {2887const Form *frm = globals[_type];2888if (frm == NULL) return NULL;2889OperandForm *op = frm->is_operand();2890if (op == NULL) return NULL;2891if (op->ideal_only()) return op->_ident;2892return (char *)op->ideal_type(globals);2893}28942895void Component::dump() {2896output(stderr);2897}28982899void Component::output(FILE *fp) {2900fprintf(fp,"Component:"); // Write to output files2901fprintf(fp, " name = %s", _name);2902fprintf(fp, ", type = %s", _type);2903assert(_usedef != 0, "unknown effect");2904fprintf(fp, ", use/def = %s\n", getUsedefName());2905}290629072908//------------------------------ComponentList---------------------------------2909ComponentList::ComponentList() : NameList(), _matchcnt(0) {2910}2911ComponentList::~ComponentList() {2912// // This list may not own its elements if copied via assignment2913// Component *component;2914// for (reset(); (component = iter()) != NULL;) {2915// delete component;2916// }2917}29182919void ComponentList::insert(Component *component, bool mflag) {2920NameList::addName((char *)component);2921if(mflag) _matchcnt++;2922}2923void ComponentList::insert(const char *name, const char *opType, int usedef,2924bool mflag) {2925Component * component = new Component(name, opType, usedef);2926insert(component, mflag);2927}2928Component *ComponentList::current() { return (Component*)NameList::current(); }2929Component *ComponentList::iter() { return (Component*)NameList::iter(); }2930Component *ComponentList::match_iter() {2931if(_iter < _matchcnt) return (Component*)NameList::iter();2932return NULL;2933}2934Component *ComponentList::post_match_iter() {2935Component *comp = iter();2936// At end of list?2937if ( comp == NULL ) {2938return comp;2939}2940// In post-match components?2941if (_iter > match_count()-1) {2942return comp;2943}29442945return post_match_iter();2946}29472948void ComponentList::reset() { NameList::reset(); }2949int ComponentList::count() { return NameList::count(); }29502951Component *ComponentList::operator[](int position) {2952// Shortcut complete iteration if there are not enough entries2953if (position >= count()) return NULL;29542955int index = 0;2956Component *component = NULL;2957for (reset(); (component = iter()) != NULL;) {2958if (index == position) {2959return component;2960}2961++index;2962}29632964return NULL;2965}29662967const Component *ComponentList::search(const char *name) {2968PreserveIter pi(this);2969reset();2970for( Component *comp = NULL; ((comp = iter()) != NULL); ) {2971if( strcmp(comp->_name,name) == 0 ) return comp;2972}29732974return NULL;2975}29762977// Return number of USEs + number of DEFs2978// When there are no components, or the first component is a USE,2979// then we add '1' to hold a space for the 'result' operand.2980int ComponentList::num_operands() {2981PreserveIter pi(this);2982uint count = 1; // result operand2983uint position = 0;29842985Component *component = NULL;2986for( reset(); (component = iter()) != NULL; ++position ) {2987if( component->isa(Component::USE) ||2988( position == 0 && (! component->isa(Component::DEF))) ) {2989++count;2990}2991}29922993return count;2994}29952996// Return zero-based position of operand 'name' in list; -1 if not in list.2997// if parameter 'usedef' is ::USE, it will match USE, USE_DEF, ...2998int ComponentList::operand_position(const char *name, int usedef, Form *fm) {2999PreserveIter pi(this);3000int position = 0;3001int num_opnds = num_operands();3002Component *component;3003Component* preceding_non_use = NULL;3004Component* first_def = NULL;3005for (reset(); (component = iter()) != NULL; ++position) {3006// When the first component is not a DEF,3007// leave space for the result operand!3008if ( position==0 && (! component->isa(Component::DEF)) ) {3009++position;3010++num_opnds;3011}3012if (strcmp(name, component->_name)==0 && (component->isa(usedef))) {3013// When the first entry in the component list is a DEF and a USE3014// Treat them as being separate, a DEF first, then a USE3015if( position==03016&& usedef==Component::USE && component->isa(Component::DEF) ) {3017assert(position+1 < num_opnds, "advertised index in bounds");3018return position+1;3019} else {3020if( preceding_non_use && strcmp(component->_name, preceding_non_use->_name) ) {3021fprintf(stderr, "the name '%s(%s)' should not precede the name '%s(%s)'",3022preceding_non_use->_name, preceding_non_use->getUsedefName(),3023name, component->getUsedefName());3024if (fm && fm->is_instruction()) fprintf(stderr, "in form '%s'", fm->is_instruction()->_ident);3025if (fm && fm->is_operand()) fprintf(stderr, "in form '%s'", fm->is_operand()->_ident);3026fprintf(stderr, "\n");3027}3028if( position >= num_opnds ) {3029fprintf(stderr, "the name '%s' is too late in its name list", name);3030if (fm && fm->is_instruction()) fprintf(stderr, "in form '%s'", fm->is_instruction()->_ident);3031if (fm && fm->is_operand()) fprintf(stderr, "in form '%s'", fm->is_operand()->_ident);3032fprintf(stderr, "\n");3033}3034assert(position < num_opnds, "advertised index in bounds");3035return position;3036}3037}3038if( component->isa(Component::DEF)3039&& component->isa(Component::USE) ) {3040++position;3041if( position != 1 ) --position; // only use two slots for the 1st USE_DEF3042}3043if( component->isa(Component::DEF) && !first_def ) {3044first_def = component;3045}3046if( !component->isa(Component::USE) && component != first_def ) {3047preceding_non_use = component;3048} else if( preceding_non_use && !strcmp(component->_name, preceding_non_use->_name) ) {3049preceding_non_use = NULL;3050}3051}3052return Not_in_list;3053}30543055// Find position for this name, regardless of use/def information3056int ComponentList::operand_position(const char *name) {3057PreserveIter pi(this);3058int position = 0;3059Component *component;3060for (reset(); (component = iter()) != NULL; ++position) {3061// When the first component is not a DEF,3062// leave space for the result operand!3063if ( position==0 && (! component->isa(Component::DEF)) ) {3064++position;3065}3066if (strcmp(name, component->_name)==0) {3067return position;3068}3069if( component->isa(Component::DEF)3070&& component->isa(Component::USE) ) {3071++position;3072if( position != 1 ) --position; // only use two slots for the 1st USE_DEF3073}3074}3075return Not_in_list;3076}30773078int ComponentList::operand_position_format(const char *name, Form *fm) {3079PreserveIter pi(this);3080int first_position = operand_position(name);3081int use_position = operand_position(name, Component::USE, fm);30823083return ((first_position < use_position) ? use_position : first_position);3084}30853086int ComponentList::label_position() {3087PreserveIter pi(this);3088int position = 0;3089reset();3090for( Component *comp; (comp = iter()) != NULL; ++position) {3091// When the first component is not a DEF,3092// leave space for the result operand!3093if ( position==0 && (! comp->isa(Component::DEF)) ) {3094++position;3095}3096if (strcmp(comp->_type, "label")==0) {3097return position;3098}3099if( comp->isa(Component::DEF)3100&& comp->isa(Component::USE) ) {3101++position;3102if( position != 1 ) --position; // only use two slots for the 1st USE_DEF3103}3104}31053106return -1;3107}31083109int ComponentList::method_position() {3110PreserveIter pi(this);3111int position = 0;3112reset();3113for( Component *comp; (comp = iter()) != NULL; ++position) {3114// When the first component is not a DEF,3115// leave space for the result operand!3116if ( position==0 && (! comp->isa(Component::DEF)) ) {3117++position;3118}3119if (strcmp(comp->_type, "method")==0) {3120return position;3121}3122if( comp->isa(Component::DEF)3123&& comp->isa(Component::USE) ) {3124++position;3125if( position != 1 ) --position; // only use two slots for the 1st USE_DEF3126}3127}31283129return -1;3130}31313132void ComponentList::dump() { output(stderr); }31333134void ComponentList::output(FILE *fp) {3135PreserveIter pi(this);3136fprintf(fp, "\n");3137Component *component;3138for (reset(); (component = iter()) != NULL;) {3139component->output(fp);3140}3141fprintf(fp, "\n");3142}31433144//------------------------------MatchNode--------------------------------------3145MatchNode::MatchNode(ArchDesc &ad, const char *result, const char *mexpr,3146const char *opType, MatchNode *lChild, MatchNode *rChild)3147: _AD(ad), _result(result), _name(mexpr), _opType(opType),3148_lChild(lChild), _rChild(rChild), _internalop(0), _numleaves(0),3149_commutative_id(0) {3150_numleaves = (lChild ? lChild->_numleaves : 0)3151+ (rChild ? rChild->_numleaves : 0);3152}31533154MatchNode::MatchNode(ArchDesc &ad, MatchNode& mnode)3155: _AD(ad), _result(mnode._result), _name(mnode._name),3156_opType(mnode._opType), _lChild(mnode._lChild), _rChild(mnode._rChild),3157_internalop(0), _numleaves(mnode._numleaves),3158_commutative_id(mnode._commutative_id) {3159}31603161MatchNode::MatchNode(ArchDesc &ad, MatchNode& mnode, int clone)3162: _AD(ad), _result(mnode._result), _name(mnode._name),3163_opType(mnode._opType),3164_internalop(0), _numleaves(mnode._numleaves),3165_commutative_id(mnode._commutative_id) {3166if (mnode._lChild) {3167_lChild = new MatchNode(ad, *mnode._lChild, clone);3168} else {3169_lChild = NULL;3170}3171if (mnode._rChild) {3172_rChild = new MatchNode(ad, *mnode._rChild, clone);3173} else {3174_rChild = NULL;3175}3176}31773178MatchNode::~MatchNode() {3179// // This node may not own its children if copied via assignment3180// if( _lChild ) delete _lChild;3181// if( _rChild ) delete _rChild;3182}31833184bool MatchNode::find_type(const char *type, int &position) const {3185if ( (_lChild != NULL) && (_lChild->find_type(type, position)) ) return true;3186if ( (_rChild != NULL) && (_rChild->find_type(type, position)) ) return true;31873188if (strcmp(type,_opType)==0) {3189return true;3190} else {3191++position;3192}3193return false;3194}31953196// Recursive call collecting info on top-level operands, not transitive.3197// Implementation does not modify state of internal structures.3198void MatchNode::append_components(FormDict& locals, ComponentList& components,3199bool def_flag) const {3200int usedef = def_flag ? Component::DEF : Component::USE;3201FormDict &globals = _AD.globalNames();32023203assert (_name != NULL, "MatchNode::build_components encountered empty node\n");3204// Base case3205if (_lChild==NULL && _rChild==NULL) {3206// If _opType is not an operation, do not build a component for it #####3207const Form *f = globals[_opType];3208if( f != NULL ) {3209// Add non-ideals that are operands, operand-classes,3210if( ! f->ideal_only()3211&& (f->is_opclass() || f->is_operand()) ) {3212components.insert(_name, _opType, usedef, true);3213}3214}3215return;3216}3217// Promote results of "Set" to DEF3218bool tmpdef_flag = (!strcmp(_opType, "Set")) ? true : false;3219if (_lChild) _lChild->append_components(locals, components, tmpdef_flag);3220tmpdef_flag = false; // only applies to component immediately following 'Set'3221if (_rChild) _rChild->append_components(locals, components, tmpdef_flag);3222}32233224// Find the n'th base-operand in the match node,3225// recursively investigates match rules of user-defined operands.3226//3227// Implementation does not modify state of internal structures since they3228// can be shared.3229bool MatchNode::base_operand(uint &position, FormDict &globals,3230const char * &result, const char * &name,3231const char * &opType) const {3232assert (_name != NULL, "MatchNode::base_operand encountered empty node\n");3233// Base case3234if (_lChild==NULL && _rChild==NULL) {3235// Check for special case: "Universe", "label"3236if (strcmp(_opType,"Universe") == 0 || strcmp(_opType,"label")==0 ) {3237if (position == 0) {3238result = _result;3239name = _name;3240opType = _opType;3241return 1;3242} else {3243-- position;3244return 0;3245}3246}32473248const Form *form = globals[_opType];3249MatchNode *matchNode = NULL;3250// Check for user-defined type3251if (form) {3252// User operand or instruction?3253OperandForm *opForm = form->is_operand();3254InstructForm *inForm = form->is_instruction();3255if ( opForm ) {3256matchNode = (MatchNode*)opForm->_matrule;3257} else if ( inForm ) {3258matchNode = (MatchNode*)inForm->_matrule;3259}3260}3261// if this is user-defined, recurse on match rule3262// User-defined operand and instruction forms have a match-rule.3263if (matchNode) {3264return (matchNode->base_operand(position,globals,result,name,opType));3265} else {3266// Either not a form, or a system-defined form (no match rule).3267if (position==0) {3268result = _result;3269name = _name;3270opType = _opType;3271return 1;3272} else {3273--position;3274return 0;3275}3276}32773278} else {3279// Examine the left child and right child as well3280if (_lChild) {3281if (_lChild->base_operand(position, globals, result, name, opType))3282return 1;3283}32843285if (_rChild) {3286if (_rChild->base_operand(position, globals, result, name, opType))3287return 1;3288}3289}32903291return 0;3292}32933294// Recursive call on all operands' match rules in my match rule.3295uint MatchNode::num_consts(FormDict &globals) const {3296uint index = 0;3297uint num_consts = 0;3298const char *result;3299const char *name;3300const char *opType;33013302for (uint position = index;3303base_operand(position,globals,result,name,opType); position = index) {3304++index;3305if( ideal_to_const_type(opType) ) num_consts++;3306}33073308return num_consts;3309}33103311// Recursive call on all operands' match rules in my match rule.3312// Constants in match rule subtree with specified type3313uint MatchNode::num_consts(FormDict &globals, Form::DataType type) const {3314uint index = 0;3315uint num_consts = 0;3316const char *result;3317const char *name;3318const char *opType;33193320for (uint position = index;3321base_operand(position,globals,result,name,opType); position = index) {3322++index;3323if( ideal_to_const_type(opType) == type ) num_consts++;3324}33253326return num_consts;3327}33283329// Recursive call on all operands' match rules in my match rule.3330uint MatchNode::num_const_ptrs(FormDict &globals) const {3331return num_consts( globals, Form::idealP );3332}33333334bool MatchNode::sets_result() const {3335return ( (strcmp(_name,"Set") == 0) ? true : false );3336}33373338const char *MatchNode::reduce_right(FormDict &globals) const {3339// If there is no right reduction, return NULL.3340const char *rightStr = NULL;33413342// If we are a "Set", start from the right child.3343const MatchNode *const mnode = sets_result() ?3344(const MatchNode *)this->_rChild :3345(const MatchNode *)this;33463347// If our right child exists, it is the right reduction3348if ( mnode->_rChild ) {3349rightStr = mnode->_rChild->_internalop ? mnode->_rChild->_internalop3350: mnode->_rChild->_opType;3351}3352// Else, May be simple chain rule: (Set dst operand_form), rightStr=NULL;3353return rightStr;3354}33553356const char *MatchNode::reduce_left(FormDict &globals) const {3357// If there is no left reduction, return NULL.3358const char *leftStr = NULL;33593360// If we are a "Set", start from the right child.3361const MatchNode *const mnode = sets_result() ?3362(const MatchNode *)this->_rChild :3363(const MatchNode *)this;33643365// If our left child exists, it is the left reduction3366if ( mnode->_lChild ) {3367leftStr = mnode->_lChild->_internalop ? mnode->_lChild->_internalop3368: mnode->_lChild->_opType;3369} else {3370// May be simple chain rule: (Set dst operand_form_source)3371if ( sets_result() ) {3372OperandForm *oper = globals[mnode->_opType]->is_operand();3373if( oper ) {3374leftStr = mnode->_opType;3375}3376}3377}3378return leftStr;3379}33803381//------------------------------count_instr_names------------------------------3382// Count occurrences of operands names in the leaves of the instruction3383// match rule.3384void MatchNode::count_instr_names( Dict &names ) {3385if( this == NULL ) return;3386if( _lChild ) _lChild->count_instr_names(names);3387if( _rChild ) _rChild->count_instr_names(names);3388if( !_lChild && !_rChild ) {3389uintptr_t cnt = (uintptr_t)names[_name];3390cnt++; // One more name found3391names.Insert(_name,(void*)cnt);3392}3393}33943395//------------------------------build_instr_pred-------------------------------3396// Build a path to 'name' in buf. Actually only build if cnt is zero, so we3397// can skip some leading instances of 'name'.3398int MatchNode::build_instr_pred( char *buf, const char *name, int cnt ) {3399if( _lChild ) {3400if( !cnt ) strcpy( buf, "_kids[0]->" );3401cnt = _lChild->build_instr_pred( buf+strlen(buf), name, cnt );3402if( cnt < 0 ) return cnt; // Found it, all done3403}3404if( _rChild ) {3405if( !cnt ) strcpy( buf, "_kids[1]->" );3406cnt = _rChild->build_instr_pred( buf+strlen(buf), name, cnt );3407if( cnt < 0 ) return cnt; // Found it, all done3408}3409if( !_lChild && !_rChild ) { // Found a leaf3410// Wrong name? Give up...3411if( strcmp(name,_name) ) return cnt;3412if( !cnt ) strcpy(buf,"_leaf");3413return cnt-1;3414}3415return cnt;3416}341734183419//------------------------------build_internalop-------------------------------3420// Build string representation of subtree3421void MatchNode::build_internalop( ) {3422char *iop, *subtree;3423const char *lstr, *rstr;3424// Build string representation of subtree3425// Operation lchildType rchildType3426int len = (int)strlen(_opType) + 4;3427lstr = (_lChild) ? ((_lChild->_internalop) ?3428_lChild->_internalop : _lChild->_opType) : "";3429rstr = (_rChild) ? ((_rChild->_internalop) ?3430_rChild->_internalop : _rChild->_opType) : "";3431len += (int)strlen(lstr) + (int)strlen(rstr);3432subtree = (char *)malloc(len);3433sprintf(subtree,"_%s_%s_%s", _opType, lstr, rstr);3434// Hash the subtree string in _internalOps; if a name exists, use it3435iop = (char *)_AD._internalOps[subtree];3436// Else create a unique name, and add it to the hash table3437if (iop == NULL) {3438iop = subtree;3439_AD._internalOps.Insert(subtree, iop);3440_AD._internalOpNames.addName(iop);3441_AD._internalMatch.Insert(iop, this);3442}3443// Add the internal operand name to the MatchNode3444_internalop = iop;3445_result = iop;3446}344734483449void MatchNode::dump() {3450output(stderr);3451}34523453void MatchNode::output(FILE *fp) {3454if (_lChild==0 && _rChild==0) {3455fprintf(fp," %s",_name); // operand3456}3457else {3458fprintf(fp," (%s ",_name); // " (opcodeName "3459if(_lChild) _lChild->output(fp); // left operand3460if(_rChild) _rChild->output(fp); // right operand3461fprintf(fp,")"); // ")"3462}3463}34643465int MatchNode::needs_ideal_memory_edge(FormDict &globals) const {3466static const char *needs_ideal_memory_list[] = {3467"StoreI","StoreL","StoreP","StoreN","StoreNKlass","StoreD","StoreF" ,3468"StoreB","StoreC","Store" ,"StoreFP",3469"LoadI", "LoadL", "LoadP" ,"LoadN", "LoadD" ,"LoadF" ,3470"LoadB" , "LoadUB", "LoadUS" ,"LoadS" ,"Load" ,3471"StoreVector", "LoadVector",3472"LoadRange", "LoadKlass", "LoadNKlass", "LoadL_unaligned", "LoadD_unaligned",3473"LoadPLocked",3474"StorePConditional", "StoreIConditional", "StoreLConditional",3475"CompareAndSwapI", "CompareAndSwapL", "CompareAndSwapP", "CompareAndSwapN",3476"ShenandoahCompareAndSwapN", "ShenandoahCompareAndSwapP",3477"StoreCM",3478"ClearArray",3479"GetAndAddI", "GetAndSetI", "GetAndSetP",3480"GetAndAddL", "GetAndSetL", "GetAndSetN",3481};3482int cnt = sizeof(needs_ideal_memory_list)/sizeof(char*);3483if( strcmp(_opType,"PrefetchRead")==0 ||3484strcmp(_opType,"PrefetchWrite")==0 ||3485strcmp(_opType,"PrefetchAllocation")==0 )3486return 1;3487if( _lChild ) {3488const char *opType = _lChild->_opType;3489for( int i=0; i<cnt; i++ )3490if( strcmp(opType,needs_ideal_memory_list[i]) == 0 )3491return 1;3492if( _lChild->needs_ideal_memory_edge(globals) )3493return 1;3494}3495if( _rChild ) {3496const char *opType = _rChild->_opType;3497for( int i=0; i<cnt; i++ )3498if( strcmp(opType,needs_ideal_memory_list[i]) == 0 )3499return 1;3500if( _rChild->needs_ideal_memory_edge(globals) )3501return 1;3502}35033504return 0;3505}35063507// TRUE if defines a derived oop, and so needs a base oop edge present3508// post-matching.3509int MatchNode::needs_base_oop_edge() const {3510if( !strcmp(_opType,"AddP") ) return 1;3511if( strcmp(_opType,"Set") ) return 0;3512return !strcmp(_rChild->_opType,"AddP");3513}35143515int InstructForm::needs_base_oop_edge(FormDict &globals) const {3516if( is_simple_chain_rule(globals) ) {3517const char *src = _matrule->_rChild->_opType;3518OperandForm *src_op = globals[src]->is_operand();3519assert( src_op, "Not operand class of chain rule" );3520return src_op->_matrule ? src_op->_matrule->needs_base_oop_edge() : 0;3521} // Else check instruction35223523return _matrule ? _matrule->needs_base_oop_edge() : 0;3524}352535263527//-------------------------cisc spilling methods-------------------------------3528// helper routines and methods for detecting cisc-spilling instructions3529//-------------------------cisc_spill_merge------------------------------------3530int MatchNode::cisc_spill_merge(int left_spillable, int right_spillable) {3531int cisc_spillable = Maybe_cisc_spillable;35323533// Combine results of left and right checks3534if( (left_spillable == Maybe_cisc_spillable) && (right_spillable == Maybe_cisc_spillable) ) {3535// neither side is spillable, nor prevents cisc spilling3536cisc_spillable = Maybe_cisc_spillable;3537}3538else if( (left_spillable == Maybe_cisc_spillable) && (right_spillable > Maybe_cisc_spillable) ) {3539// right side is spillable3540cisc_spillable = right_spillable;3541}3542else if( (right_spillable == Maybe_cisc_spillable) && (left_spillable > Maybe_cisc_spillable) ) {3543// left side is spillable3544cisc_spillable = left_spillable;3545}3546else if( (left_spillable == Not_cisc_spillable) || (right_spillable == Not_cisc_spillable) ) {3547// left or right prevents cisc spilling this instruction3548cisc_spillable = Not_cisc_spillable;3549}3550else {3551// Only allow one to spill3552cisc_spillable = Not_cisc_spillable;3553}35543555return cisc_spillable;3556}35573558//-------------------------root_ops_match--------------------------------------3559bool static root_ops_match(FormDict &globals, const char *op1, const char *op2) {3560// Base Case: check that the current operands/operations match3561assert( op1, "Must have op's name");3562assert( op2, "Must have op's name");3563const Form *form1 = globals[op1];3564const Form *form2 = globals[op2];35653566return (form1 == form2);3567}35683569//-------------------------cisc_spill_match_node-------------------------------3570// Recursively check two MatchRules for legal conversion via cisc-spilling3571int MatchNode::cisc_spill_match(FormDict& globals, RegisterForm* registers, MatchNode* mRule2, const char* &operand, const char* ®_type) {3572int cisc_spillable = Maybe_cisc_spillable;3573int left_spillable = Maybe_cisc_spillable;3574int right_spillable = Maybe_cisc_spillable;35753576// Check that each has same number of operands at this level3577if( (_lChild && !(mRule2->_lChild)) || (_rChild && !(mRule2->_rChild)) )3578return Not_cisc_spillable;35793580// Base Case: check that the current operands/operations match3581// or are CISC spillable3582assert( _opType, "Must have _opType");3583assert( mRule2->_opType, "Must have _opType");3584const Form *form = globals[_opType];3585const Form *form2 = globals[mRule2->_opType];3586if( form == form2 ) {3587cisc_spillable = Maybe_cisc_spillable;3588} else {3589const InstructForm *form2_inst = form2 ? form2->is_instruction() : NULL;3590const char *name_left = mRule2->_lChild ? mRule2->_lChild->_opType : NULL;3591const char *name_right = mRule2->_rChild ? mRule2->_rChild->_opType : NULL;3592DataType data_type = Form::none;3593if (form->is_operand()) {3594// Make sure the loadX matches the type of the reg3595data_type = form->ideal_to_Reg_type(form->is_operand()->ideal_type(globals));3596}3597// Detect reg vs (loadX memory)3598if( form->is_cisc_reg(globals)3599&& form2_inst3600&& data_type != Form::none3601&& (is_load_from_memory(mRule2->_opType) == data_type) // reg vs. (load memory)3602&& (name_left != NULL) // NOT (load)3603&& (name_right == NULL) ) { // NOT (load memory foo)3604const Form *form2_left = name_left ? globals[name_left] : NULL;3605if( form2_left && form2_left->is_cisc_mem(globals) ) {3606cisc_spillable = Is_cisc_spillable;3607operand = _name;3608reg_type = _result;3609return Is_cisc_spillable;3610} else {3611cisc_spillable = Not_cisc_spillable;3612}3613}3614// Detect reg vs memory3615else if( form->is_cisc_reg(globals) && form2->is_cisc_mem(globals) ) {3616cisc_spillable = Is_cisc_spillable;3617operand = _name;3618reg_type = _result;3619return Is_cisc_spillable;3620} else {3621cisc_spillable = Not_cisc_spillable;3622}3623}36243625// If cisc is still possible, check rest of tree3626if( cisc_spillable == Maybe_cisc_spillable ) {3627// Check that each has same number of operands at this level3628if( (_lChild && !(mRule2->_lChild)) || (_rChild && !(mRule2->_rChild)) ) return Not_cisc_spillable;36293630// Check left operands3631if( (_lChild == NULL) && (mRule2->_lChild == NULL) ) {3632left_spillable = Maybe_cisc_spillable;3633} else {3634left_spillable = _lChild->cisc_spill_match(globals, registers, mRule2->_lChild, operand, reg_type);3635}36363637// Check right operands3638if( (_rChild == NULL) && (mRule2->_rChild == NULL) ) {3639right_spillable = Maybe_cisc_spillable;3640} else {3641right_spillable = _rChild->cisc_spill_match(globals, registers, mRule2->_rChild, operand, reg_type);3642}36433644// Combine results of left and right checks3645cisc_spillable = cisc_spill_merge(left_spillable, right_spillable);3646}36473648return cisc_spillable;3649}36503651//---------------------------cisc_spill_match_rule------------------------------3652// Recursively check two MatchRules for legal conversion via cisc-spilling3653// This method handles the root of Match tree,3654// general recursive checks done in MatchNode3655int MatchRule::matchrule_cisc_spill_match(FormDict& globals, RegisterForm* registers,3656MatchRule* mRule2, const char* &operand,3657const char* ®_type) {3658int cisc_spillable = Maybe_cisc_spillable;3659int left_spillable = Maybe_cisc_spillable;3660int right_spillable = Maybe_cisc_spillable;36613662// Check that each sets a result3663if( !(sets_result() && mRule2->sets_result()) ) return Not_cisc_spillable;3664// Check that each has same number of operands at this level3665if( (_lChild && !(mRule2->_lChild)) || (_rChild && !(mRule2->_rChild)) ) return Not_cisc_spillable;36663667// Check left operands: at root, must be target of 'Set'3668if( (_lChild == NULL) || (mRule2->_lChild == NULL) ) {3669left_spillable = Not_cisc_spillable;3670} else {3671// Do not support cisc-spilling instruction's target location3672if( root_ops_match(globals, _lChild->_opType, mRule2->_lChild->_opType) ) {3673left_spillable = Maybe_cisc_spillable;3674} else {3675left_spillable = Not_cisc_spillable;3676}3677}36783679// Check right operands: recursive walk to identify reg->mem operand3680if( (_rChild == NULL) && (mRule2->_rChild == NULL) ) {3681right_spillable = Maybe_cisc_spillable;3682} else {3683right_spillable = _rChild->cisc_spill_match(globals, registers, mRule2->_rChild, operand, reg_type);3684}36853686// Combine results of left and right checks3687cisc_spillable = cisc_spill_merge(left_spillable, right_spillable);36883689return cisc_spillable;3690}36913692//----------------------------- equivalent ------------------------------------3693// Recursively check to see if two match rules are equivalent.3694// This rule handles the root.3695bool MatchRule::equivalent(FormDict &globals, MatchNode *mRule2) {3696// Check that each sets a result3697if (sets_result() != mRule2->sets_result()) {3698return false;3699}37003701// Check that the current operands/operations match3702assert( _opType, "Must have _opType");3703assert( mRule2->_opType, "Must have _opType");3704const Form *form = globals[_opType];3705const Form *form2 = globals[mRule2->_opType];3706if( form != form2 ) {3707return false;3708}37093710if (_lChild ) {3711if( !_lChild->equivalent(globals, mRule2->_lChild) )3712return false;3713} else if (mRule2->_lChild) {3714return false; // I have NULL left child, mRule2 has non-NULL left child.3715}37163717if (_rChild ) {3718if( !_rChild->equivalent(globals, mRule2->_rChild) )3719return false;3720} else if (mRule2->_rChild) {3721return false; // I have NULL right child, mRule2 has non-NULL right child.3722}37233724// We've made it through the gauntlet.3725return true;3726}37273728//----------------------------- equivalent ------------------------------------3729// Recursively check to see if two match rules are equivalent.3730// This rule handles the operands.3731bool MatchNode::equivalent(FormDict &globals, MatchNode *mNode2) {3732if( !mNode2 )3733return false;37343735// Check that the current operands/operations match3736assert( _opType, "Must have _opType");3737assert( mNode2->_opType, "Must have _opType");3738const Form *form = globals[_opType];3739const Form *form2 = globals[mNode2->_opType];3740if( form != form2 ) {3741return false;3742}37433744// Check that their children also match3745if (_lChild ) {3746if( !_lChild->equivalent(globals, mNode2->_lChild) )3747return false;3748} else if (mNode2->_lChild) {3749return false; // I have NULL left child, mNode2 has non-NULL left child.3750}37513752if (_rChild ) {3753if( !_rChild->equivalent(globals, mNode2->_rChild) )3754return false;3755} else if (mNode2->_rChild) {3756return false; // I have NULL right child, mNode2 has non-NULL right child.3757}37583759// We've made it through the gauntlet.3760return true;3761}37623763//-------------------------- has_commutative_op -------------------------------3764// Recursively check for commutative operations with subtree operands3765// which could be swapped.3766void MatchNode::count_commutative_op(int& count) {3767static const char *commut_op_list[] = {3768"AddI","AddL","AddF","AddD",3769"AndI","AndL",3770"MaxI","MinI",3771"MulI","MulL","MulF","MulD",3772"OrI" ,"OrL" ,3773"XorI","XorL"3774};3775int cnt = sizeof(commut_op_list)/sizeof(char*);37763777if( _lChild && _rChild && (_lChild->_lChild || _rChild->_lChild) ) {3778// Don't swap if right operand is an immediate constant.3779bool is_const = false;3780if( _rChild->_lChild == NULL && _rChild->_rChild == NULL ) {3781FormDict &globals = _AD.globalNames();3782const Form *form = globals[_rChild->_opType];3783if ( form ) {3784OperandForm *oper = form->is_operand();3785if( oper && oper->interface_type(globals) == Form::constant_interface )3786is_const = true;3787}3788}3789if( !is_const ) {3790for( int i=0; i<cnt; i++ ) {3791if( strcmp(_opType, commut_op_list[i]) == 0 ) {3792count++;3793_commutative_id = count; // id should be > 03794break;3795}3796}3797}3798}3799if( _lChild )3800_lChild->count_commutative_op(count);3801if( _rChild )3802_rChild->count_commutative_op(count);3803}38043805//-------------------------- swap_commutative_op ------------------------------3806// Recursively swap specified commutative operation with subtree operands.3807void MatchNode::swap_commutative_op(bool atroot, int id) {3808if( _commutative_id == id ) { // id should be > 03809assert(_lChild && _rChild && (_lChild->_lChild || _rChild->_lChild ),3810"not swappable operation");3811MatchNode* tmp = _lChild;3812_lChild = _rChild;3813_rChild = tmp;3814// Don't exit here since we need to build internalop.3815}38163817bool is_set = ( strcmp(_opType, "Set") == 0 );3818if( _lChild )3819_lChild->swap_commutative_op(is_set, id);3820if( _rChild )3821_rChild->swap_commutative_op(is_set, id);38223823// If not the root, reduce this subtree to an internal operand3824if( !atroot && (_lChild || _rChild) ) {3825build_internalop();3826}3827}38283829//-------------------------- swap_commutative_op ------------------------------3830// Recursively swap specified commutative operation with subtree operands.3831void MatchRule::matchrule_swap_commutative_op(const char* instr_ident, int count, int& match_rules_cnt) {3832assert(match_rules_cnt < 100," too many match rule clones");3833// Clone3834MatchRule* clone = new MatchRule(_AD, this);3835// Swap operands of commutative operation3836((MatchNode*)clone)->swap_commutative_op(true, count);3837char* buf = (char*) malloc(strlen(instr_ident) + 4);3838sprintf(buf, "%s_%d", instr_ident, match_rules_cnt++);3839clone->_result = buf;38403841clone->_next = this->_next;3842this-> _next = clone;3843if( (--count) > 0 ) {3844this-> matchrule_swap_commutative_op(instr_ident, count, match_rules_cnt);3845clone->matchrule_swap_commutative_op(instr_ident, count, match_rules_cnt);3846}3847}38483849//------------------------------MatchRule--------------------------------------3850MatchRule::MatchRule(ArchDesc &ad)3851: MatchNode(ad), _depth(0), _construct(NULL), _numchilds(0) {3852_next = NULL;3853}38543855MatchRule::MatchRule(ArchDesc &ad, MatchRule* mRule)3856: MatchNode(ad, *mRule, 0), _depth(mRule->_depth),3857_construct(mRule->_construct), _numchilds(mRule->_numchilds) {3858_next = NULL;3859}38603861MatchRule::MatchRule(ArchDesc &ad, MatchNode* mroot, int depth, char *cnstr,3862int numleaves)3863: MatchNode(ad,*mroot), _depth(depth), _construct(cnstr),3864_numchilds(0) {3865_next = NULL;3866mroot->_lChild = NULL;3867mroot->_rChild = NULL;3868delete mroot;3869_numleaves = numleaves;3870_numchilds = (_lChild ? 1 : 0) + (_rChild ? 1 : 0);3871}3872MatchRule::~MatchRule() {3873}38743875// Recursive call collecting info on top-level operands, not transitive.3876// Implementation does not modify state of internal structures.3877void MatchRule::append_components(FormDict& locals, ComponentList& components, bool def_flag) const {3878assert (_name != NULL, "MatchNode::build_components encountered empty node\n");38793880MatchNode::append_components(locals, components,3881false /* not necessarily a def */);3882}38833884// Recursive call on all operands' match rules in my match rule.3885// Implementation does not modify state of internal structures since they3886// can be shared.3887// The MatchNode that is called first treats its3888bool MatchRule::base_operand(uint &position0, FormDict &globals,3889const char *&result, const char * &name,3890const char * &opType)const{3891uint position = position0;38923893return (MatchNode::base_operand( position, globals, result, name, opType));3894}389538963897bool MatchRule::is_base_register(FormDict &globals) const {3898uint position = 1;3899const char *result = NULL;3900const char *name = NULL;3901const char *opType = NULL;3902if (!base_operand(position, globals, result, name, opType)) {3903position = 0;3904if( base_operand(position, globals, result, name, opType) &&3905(strcmp(opType,"RegI")==0 ||3906strcmp(opType,"RegP")==0 ||3907strcmp(opType,"RegN")==0 ||3908strcmp(opType,"RegL")==0 ||3909strcmp(opType,"RegF")==0 ||3910strcmp(opType,"RegD")==0 ||3911strcmp(opType,"VecS")==0 ||3912strcmp(opType,"VecD")==0 ||3913strcmp(opType,"VecX")==0 ||3914strcmp(opType,"VecY")==0 ||3915strcmp(opType,"Reg" )==0) ) {3916return 1;3917}3918}3919return 0;3920}39213922Form::DataType MatchRule::is_base_constant(FormDict &globals) const {3923uint position = 1;3924const char *result = NULL;3925const char *name = NULL;3926const char *opType = NULL;3927if (!base_operand(position, globals, result, name, opType)) {3928position = 0;3929if (base_operand(position, globals, result, name, opType)) {3930return ideal_to_const_type(opType);3931}3932}3933return Form::none;3934}39353936bool MatchRule::is_chain_rule(FormDict &globals) const {39373938// Check for chain rule, and do not generate a match list for it3939if ((_lChild == NULL) && (_rChild == NULL) ) {3940const Form *form = globals[_opType];3941// If this is ideal, then it is a base match, not a chain rule.3942if ( form && form->is_operand() && (!form->ideal_only())) {3943return true;3944}3945}3946// Check for "Set" form of chain rule, and do not generate a match list3947if (_rChild) {3948const char *rch = _rChild->_opType;3949const Form *form = globals[rch];3950if ((!strcmp(_opType,"Set") &&3951((form) && form->is_operand()))) {3952return true;3953}3954}3955return false;3956}39573958int MatchRule::is_ideal_copy() const {3959if (is_chain_rule(_AD.globalNames()) &&3960_lChild && strncmp(_lChild->_opType, "stackSlot", 9) == 0) {3961return 1;3962}3963return 0;3964}39653966int MatchRule::is_expensive() const {3967if( _rChild ) {3968const char *opType = _rChild->_opType;3969if( strcmp(opType,"AtanD")==0 ||3970strcmp(opType,"CosD")==0 ||3971strcmp(opType,"DivD")==0 ||3972strcmp(opType,"DivF")==0 ||3973strcmp(opType,"DivI")==0 ||3974strcmp(opType,"ExpD")==0 ||3975strcmp(opType,"LogD")==0 ||3976strcmp(opType,"Log10D")==0 ||3977strcmp(opType,"ModD")==0 ||3978strcmp(opType,"ModF")==0 ||3979strcmp(opType,"ModI")==0 ||3980strcmp(opType,"PowD")==0 ||3981strcmp(opType,"SinD")==0 ||3982strcmp(opType,"SqrtD")==0 ||3983strcmp(opType,"TanD")==0 ||3984strcmp(opType,"ConvD2F")==0 ||3985strcmp(opType,"ConvD2I")==0 ||3986strcmp(opType,"ConvD2L")==0 ||3987strcmp(opType,"ConvF2D")==0 ||3988strcmp(opType,"ConvF2I")==0 ||3989strcmp(opType,"ConvF2L")==0 ||3990strcmp(opType,"ConvI2D")==0 ||3991strcmp(opType,"ConvI2F")==0 ||3992strcmp(opType,"ConvI2L")==0 ||3993strcmp(opType,"ConvL2D")==0 ||3994strcmp(opType,"ConvL2F")==0 ||3995strcmp(opType,"ConvL2I")==0 ||3996strcmp(opType,"DecodeN")==0 ||3997strcmp(opType,"EncodeP")==0 ||3998strcmp(opType,"EncodePKlass")==0 ||3999strcmp(opType,"DecodeNKlass")==0 ||4000strcmp(opType,"RoundDouble")==0 ||4001strcmp(opType,"RoundFloat")==0 ||4002strcmp(opType,"ReverseBytesI")==0 ||4003strcmp(opType,"ReverseBytesL")==0 ||4004strcmp(opType,"ReverseBytesUS")==0 ||4005strcmp(opType,"ReverseBytesS")==0 ||4006strcmp(opType,"ReplicateB")==0 ||4007strcmp(opType,"ReplicateS")==0 ||4008strcmp(opType,"ReplicateI")==0 ||4009strcmp(opType,"ReplicateL")==0 ||4010strcmp(opType,"ReplicateF")==0 ||4011strcmp(opType,"ReplicateD")==0 ||40120 /* 0 to line up columns nicely */ )4013return 1;4014}4015return 0;4016}40174018bool MatchRule::is_ideal_if() const {4019if( !_opType ) return false;4020return4021!strcmp(_opType,"If" ) ||4022!strcmp(_opType,"CountedLoopEnd");4023}40244025bool MatchRule::is_ideal_fastlock() const {4026if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) {4027return (strcmp(_rChild->_opType,"FastLock") == 0);4028}4029return false;4030}40314032bool MatchRule::is_ideal_membar() const {4033if( !_opType ) return false;4034return4035!strcmp(_opType,"MemBarAcquire") ||4036!strcmp(_opType,"MemBarRelease") ||4037!strcmp(_opType,"MemBarAcquireLock") ||4038!strcmp(_opType,"MemBarReleaseLock") ||4039!strcmp(_opType,"LoadFence" ) ||4040!strcmp(_opType,"StoreFence") ||4041!strcmp(_opType,"MemBarVolatile") ||4042!strcmp(_opType,"MemBarCPUOrder") ||4043!strcmp(_opType,"MemBarStoreStore");4044}40454046bool MatchRule::is_ideal_loadPC() const {4047if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) {4048return (strcmp(_rChild->_opType,"LoadPC") == 0);4049}4050return false;4051}40524053bool MatchRule::is_ideal_box() const {4054if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) {4055return (strcmp(_rChild->_opType,"Box") == 0);4056}4057return false;4058}40594060bool MatchRule::is_ideal_goto() const {4061bool ideal_goto = false;40624063if( _opType && (strcmp(_opType,"Goto") == 0) ) {4064ideal_goto = true;4065}4066return ideal_goto;4067}40684069bool MatchRule::is_ideal_jump() const {4070if( _opType ) {4071if( !strcmp(_opType,"Jump") )4072return true;4073}4074return false;4075}40764077bool MatchRule::is_ideal_bool() const {4078if( _opType ) {4079if( !strcmp(_opType,"Bool") )4080return true;4081}4082return false;4083}408440854086Form::DataType MatchRule::is_ideal_load() const {4087Form::DataType ideal_load = Form::none;40884089if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) {4090const char *opType = _rChild->_opType;4091ideal_load = is_load_from_memory(opType);4092}40934094return ideal_load;4095}40964097bool MatchRule::is_vector() const {4098static const char *vector_list[] = {4099"AddVB","AddVS","AddVI","AddVL","AddVF","AddVD",4100"SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",4101"MulVS","MulVI","MulVF","MulVD",4102"DivVF","DivVD",4103"AndV" ,"XorV" ,"OrV",4104"LShiftCntV","RShiftCntV",4105"LShiftVB","LShiftVS","LShiftVI","LShiftVL",4106"RShiftVB","RShiftVS","RShiftVI","RShiftVL",4107"URShiftVB","URShiftVS","URShiftVI","URShiftVL",4108"ReplicateB","ReplicateS","ReplicateI","ReplicateL","ReplicateF","ReplicateD",4109"LoadVector","StoreVector",4110// Next are not supported currently.4111"PackB","PackS","PackI","PackL","PackF","PackD","Pack2L","Pack2D",4112"ExtractB","ExtractUB","ExtractC","ExtractS","ExtractI","ExtractL","ExtractF","ExtractD"4113};4114int cnt = sizeof(vector_list)/sizeof(char*);4115if (_rChild) {4116const char *opType = _rChild->_opType;4117for (int i=0; i<cnt; i++)4118if (strcmp(opType,vector_list[i]) == 0)4119return true;4120}4121return false;4122}412341244125bool MatchRule::skip_antidep_check() const {4126// Some loads operate on what is effectively immutable memory so we4127// should skip the anti dep computations. For some of these nodes4128// the rewritable field keeps the anti dep logic from triggering but4129// for certain kinds of LoadKlass it does not since they are4130// actually reading memory which could be rewritten by the runtime,4131// though never by generated code. This disables it uniformly for4132// the nodes that behave like this: LoadKlass, LoadNKlass and4133// LoadRange.4134if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) {4135const char *opType = _rChild->_opType;4136if (strcmp("LoadKlass", opType) == 0 ||4137strcmp("LoadNKlass", opType) == 0 ||4138strcmp("LoadRange", opType) == 0) {4139return true;4140}4141}41424143return false;4144}414541464147Form::DataType MatchRule::is_ideal_store() const {4148Form::DataType ideal_store = Form::none;41494150if ( _opType && (strcmp(_opType,"Set") == 0) && _rChild ) {4151const char *opType = _rChild->_opType;4152ideal_store = is_store_to_memory(opType);4153}41544155return ideal_store;4156}415741584159void MatchRule::dump() {4160output(stderr);4161}41624163// Write just one line.4164void MatchRule::output_short(FILE *fp) {4165fprintf(fp,"MatchRule: ( %s",_name);4166if (_lChild) _lChild->output(fp);4167if (_rChild) _rChild->output(fp);4168fprintf(fp," )");4169}41704171void MatchRule::output(FILE *fp) {4172output_short(fp);4173fprintf(fp,"\n nesting depth = %d\n", _depth);4174if (_result) fprintf(fp," Result Type = %s", _result);4175fprintf(fp,"\n");4176}41774178//------------------------------Attribute--------------------------------------4179Attribute::Attribute(char *id, char* val, int type)4180: _ident(id), _val(val), _atype(type) {4181}4182Attribute::~Attribute() {4183}41844185int Attribute::int_val(ArchDesc &ad) {4186// Make sure it is an integer constant:4187int result = 0;4188if (!_val || !ADLParser::is_int_token(_val, result)) {4189ad.syntax_err(0, "Attribute %s must have an integer value: %s",4190_ident, _val ? _val : "");4191}4192return result;4193}41944195void Attribute::dump() {4196output(stderr);4197} // Debug printer41984199// Write to output files4200void Attribute::output(FILE *fp) {4201fprintf(fp,"Attribute: %s %s\n", (_ident?_ident:""), (_val?_val:""));4202}42034204//------------------------------FormatRule----------------------------------4205FormatRule::FormatRule(char *temp)4206: _temp(temp) {4207}4208FormatRule::~FormatRule() {4209}42104211void FormatRule::dump() {4212output(stderr);4213}42144215// Write to output files4216void FormatRule::output(FILE *fp) {4217fprintf(fp,"\nFormat Rule: \n%s", (_temp?_temp:""));4218fprintf(fp,"\n");4219}422042214222