aboutsummaryrefslogtreecommitdiff
path: root/src/share
diff options
context:
space:
mode:
authorroland <none@none>2011-09-14 09:22:51 +0200
committerroland <none@none>2011-09-14 09:22:51 +0200
commit48853f94130fd784d8f3705cf706e3f34418f169 (patch)
tree13e4afeb49c82eb6e46cb876b4c79d282d73a3c0 /src/share
parent8fd496c2abb3d41f4addb573e22b5605b0171e38 (diff)
7077312: Provide a CALL effect for instruct declaration in the ad file
Summary: abstracted way to declare that the MachNode has the effect of a call (kills caller save registers, preserves callee save registers) Reviewed-by: twisti, never
Diffstat (limited to 'src/share')
-rw-r--r--src/share/vm/adlc/adlparse.cpp45
-rw-r--r--src/share/vm/adlc/adlparse.hpp2
-rw-r--r--src/share/vm/adlc/archDesc.cpp3
-rw-r--r--src/share/vm/adlc/formssel.cpp7
-rw-r--r--src/share/vm/adlc/formssel.hpp5
-rw-r--r--src/share/vm/adlc/output_h.cpp10
-rw-r--r--src/share/vm/opto/block.hpp2
-rw-r--r--src/share/vm/opto/idealGraphPrinter.cpp3
-rw-r--r--src/share/vm/opto/lcm.cpp46
-rw-r--r--src/share/vm/opto/machnode.hpp3
-rw-r--r--src/share/vm/opto/node.hpp3
11 files changed, 93 insertions, 36 deletions
diff --git a/src/share/vm/adlc/adlparse.cpp b/src/share/vm/adlc/adlparse.cpp
index e9b884752..5d9e5fd9f 100644
--- a/src/share/vm/adlc/adlparse.cpp
+++ b/src/share/vm/adlc/adlparse.cpp
@@ -3818,7 +3818,7 @@ void ADLParser::effect_parse(InstructForm *instr) {
return;
}
// Get list of effect-operand pairs and insert into dictionary
- else get_effectlist(instr->_effects, instr->_localNames);
+ else get_effectlist(instr->_effects, instr->_localNames, instr->_has_call);
// Debug Stuff
if (_AD._adl_debug > 1) fprintf(stderr,"Effect description: %s\n", desc);
@@ -4596,7 +4596,7 @@ void ADLParser::get_oplist(NameList &parameters, FormDict &operands) {
// effect, and the second must be the name of an operand defined in the
// operand list of this instruction. Stores the names with a pointer to the
// effect form in a local effects table.
-void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) {
+void ADLParser::get_effectlist(FormDict &effects, FormDict &operands, bool& has_call) {
OperandForm *opForm;
Effect *eForm;
char *ident;
@@ -4629,26 +4629,31 @@ void ADLParser::get_effectlist(FormDict &effects, FormDict &operands) {
// Debugging Stuff
if (_AD._adl_debug > 1) fprintf(stderr, "\tEffect Type: %s\t", ident);
skipws();
- // Get name of operand and check that it is in the local name table
- if( (ident = get_unique_ident(effects, "effect")) == NULL) {
- parse_err(SYNERR, "missing operand identifier in effect list\n");
- return;
- }
- const Form *form = operands[ident];
- opForm = form ? form->is_operand() : NULL;
- if( opForm == NULL ) {
- if( form && form->is_opclass() ) {
- const char* cname = form->is_opclass()->_ident;
- parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident);
- } else {
- parse_err(SYNERR, "undefined operand %s in effect list\n", ident);
+ if (eForm->is(Component::CALL)) {
+ if (_AD._adl_debug > 1) fprintf(stderr, "\n");
+ has_call = true;
+ } else {
+ // Get name of operand and check that it is in the local name table
+ if( (ident = get_unique_ident(effects, "effect")) == NULL) {
+ parse_err(SYNERR, "missing operand identifier in effect list\n");
+ return;
}
- return;
+ const Form *form = operands[ident];
+ opForm = form ? form->is_operand() : NULL;
+ if( opForm == NULL ) {
+ if( form && form->is_opclass() ) {
+ const char* cname = form->is_opclass()->_ident;
+ parse_err(SYNERR, "operand classes are illegal in effect lists (found %s %s)\n", cname, ident);
+ } else {
+ parse_err(SYNERR, "undefined operand %s in effect list\n", ident);
+ }
+ return;
+ }
+ // Add the pair to the effects table
+ effects.Insert(ident, eForm);
+ // Debugging Stuff
+ if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident);
}
- // Add the pair to the effects table
- effects.Insert(ident, eForm);
- // Debugging Stuff
- if (_AD._adl_debug > 1) fprintf(stderr, "\tOperand Name: %s\n", ident);
skipws();
} while(_curchar == ',');
diff --git a/src/share/vm/adlc/adlparse.hpp b/src/share/vm/adlc/adlparse.hpp
index ee33b88ef..8d87ab968 100644
--- a/src/share/vm/adlc/adlparse.hpp
+++ b/src/share/vm/adlc/adlparse.hpp
@@ -232,7 +232,7 @@ protected:
char *get_relation_dup(void);
void get_oplist(NameList &parameters, FormDict &operands);// Parse type-operand pairs
- void get_effectlist(FormDict &effects, FormDict &operands); // Parse effect-operand pairs
+ void get_effectlist(FormDict &effects, FormDict &operands, bool& has_call); // Parse effect-operand pairs
// Return the contents of a parenthesized expression.
// Requires initial '(' and consumes final ')', which is replaced by '\0'.
char *get_paren_expr(const char *description, bool include_location = false);
diff --git a/src/share/vm/adlc/archDesc.cpp b/src/share/vm/adlc/archDesc.cpp
index 5b4c1faad..940bb3131 100644
--- a/src/share/vm/adlc/archDesc.cpp
+++ b/src/share/vm/adlc/archDesc.cpp
@@ -1018,6 +1018,9 @@ void ArchDesc::initBaseOpTypes() {
ident = "TEMP";
eForm = new Effect(ident);
_globalNames.Insert(ident, eForm);
+ ident = "CALL";
+ eForm = new Effect(ident);
+ _globalNames.Insert(ident, eForm);
}
//
diff --git a/src/share/vm/adlc/formssel.cpp b/src/share/vm/adlc/formssel.cpp
index d3817ed4a..c1d39849b 100644
--- a/src/share/vm/adlc/formssel.cpp
+++ b/src/share/vm/adlc/formssel.cpp
@@ -31,7 +31,8 @@ InstructForm::InstructForm(const char *id, bool ideal_only)
: _ident(id), _ideal_only(ideal_only),
_localNames(cmpstr, hashstr, Form::arena),
_effects(cmpstr, hashstr, Form::arena),
- _is_mach_constant(false)
+ _is_mach_constant(false),
+ _has_call(false)
{
_ftype = Form::INS;
@@ -62,7 +63,8 @@ InstructForm::InstructForm(const char *id, InstructForm *instr, MatchRule *rule)
: _ident(id), _ideal_only(false),
_localNames(instr->_localNames),
_effects(instr->_effects),
- _is_mach_constant(false)
+ _is_mach_constant(false),
+ _has_call(false)
{
_ftype = Form::INS;
@@ -1754,6 +1756,7 @@ static int effect_lookup(const char *name) {
if(!strcmp(name, "USE_KILL")) return Component::USE_KILL;
if(!strcmp(name, "TEMP")) return Component::TEMP;
if(!strcmp(name, "INVALID")) return Component::INVALID;
+ if(!strcmp(name, "CALL")) return Component::CALL;
assert( false,"Invalid effect name specified\n");
return Component::INVALID;
}
diff --git a/src/share/vm/adlc/formssel.hpp b/src/share/vm/adlc/formssel.hpp
index 50d7a7063..b2d3ec74d 100644
--- a/src/share/vm/adlc/formssel.hpp
+++ b/src/share/vm/adlc/formssel.hpp
@@ -111,6 +111,8 @@ public:
ComponentList _components; // List of Components matches MachNode's
// operand structure
+ bool _has_call; // contain a call and caller save registers should be saved?
+
// Public Methods
InstructForm(const char *id, bool ideal_only = false);
InstructForm(const char *id, InstructForm *instr, MatchRule *rule);
@@ -895,7 +897,8 @@ public:
DEF = 0x2, USE_DEF = 0x3,
KILL = 0x4, USE_KILL = 0x5,
SYNTHETIC = 0x8,
- TEMP = USE | SYNTHETIC
+ TEMP = USE | SYNTHETIC,
+ CALL = 0x10
};
};
diff --git a/src/share/vm/adlc/output_h.cpp b/src/share/vm/adlc/output_h.cpp
index 9e609b8dc..ea066eb0d 100644
--- a/src/share/vm/adlc/output_h.cpp
+++ b/src/share/vm/adlc/output_h.cpp
@@ -1720,6 +1720,16 @@ void ArchDesc::declareClasses(FILE *fp) {
}
}
+ // flag: if this instruction is implemented with a call
+ if ( instr->_has_call ) {
+ if ( node_flags_set ) {
+ fprintf(fp," | Flag_has_call");
+ } else {
+ fprintf(fp,"init_flags(Flag_has_call");
+ node_flags_set = true;
+ }
+ }
+
if ( node_flags_set ) {
fprintf(fp,"); ");
}
diff --git a/src/share/vm/opto/block.hpp b/src/share/vm/opto/block.hpp
index 51869c8da..ef5c8d6e4 100644
--- a/src/share/vm/opto/block.hpp
+++ b/src/share/vm/opto/block.hpp
@@ -281,6 +281,8 @@ class Block : public CFGElement {
// Find and remove n from block list
void find_remove( const Node *n );
+ // helper function that adds caller save registers to MachProjNode
+ void add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe);
// Schedule a call next in the block
uint sched_call(Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, int *ready_cnt, MachCallNode *mcall, VectorSet &next_call);
diff --git a/src/share/vm/opto/idealGraphPrinter.cpp b/src/share/vm/opto/idealGraphPrinter.cpp
index a5a0c6588..f9f40a37d 100644
--- a/src/share/vm/opto/idealGraphPrinter.cpp
+++ b/src/share/vm/opto/idealGraphPrinter.cpp
@@ -447,6 +447,9 @@ void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) {
if (flags & Node::Flag_may_be_short_branch) {
print_prop("may_be_short_branch", "true");
}
+ if (flags & Node::Flag_has_call) {
+ print_prop("has_call", "true");
+ }
if (C->matcher() != NULL) {
if (C->matcher()->is_shared(node)) {
diff --git a/src/share/vm/opto/lcm.cpp b/src/share/vm/opto/lcm.cpp
index 425e10bad..287b6ed05 100644
--- a/src/share/vm/opto/lcm.cpp
+++ b/src/share/vm/opto/lcm.cpp
@@ -548,6 +548,22 @@ void Block::needed_for_next_call(Node *this_call, VectorSet &next_call, Block_Ar
set_next_call(call, next_call, bbs);
}
+//------------------------------add_call_kills-------------------------------------
+void Block::add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe) {
+ // Fill in the kill mask for the call
+ for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) {
+ if( !regs.Member(r) ) { // Not already defined by the call
+ // Save-on-call register?
+ if ((save_policy[r] == 'C') ||
+ (save_policy[r] == 'A') ||
+ ((save_policy[r] == 'E') && exclude_soe)) {
+ proj->_rout.Insert(r);
+ }
+ }
+ }
+}
+
+
//------------------------------sched_call-------------------------------------
uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_List &worklist, int *ready_cnt, MachCallNode *mcall, VectorSet &next_call ) {
RegMask regs;
@@ -631,17 +647,7 @@ uint Block::sched_call( Matcher &matcher, Block_Array &bbs, uint node_cnt, Node_
proj->_rout.OR(Matcher::method_handle_invoke_SP_save_mask());
}
- // Fill in the kill mask for the call
- for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) {
- if( !regs.Member(r) ) { // Not already defined by the call
- // Save-on-call register?
- if ((save_policy[r] == 'C') ||
- (save_policy[r] == 'A') ||
- ((save_policy[r] == 'E') && exclude_soe)) {
- proj->_rout.Insert(r);
- }
- }
- }
+ add_call_kills(proj, regs, save_policy, exclude_soe);
return node_cnt;
}
@@ -776,6 +782,7 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect
}
#endif
+ uint max_idx = matcher.C->unique();
// Pull from worklist and schedule
while( worklist.size() ) { // Worklist is not ready
@@ -815,11 +822,28 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, int *ready_cnt, Vect
phi_cnt = sched_call(matcher, cfg->_bbs, phi_cnt, worklist, ready_cnt, mcall, next_call);
continue;
}
+
+ if (n->is_Mach() && n->as_Mach()->has_call()) {
+ RegMask regs;
+ regs.Insert(matcher.c_frame_pointer());
+ regs.OR(n->out_RegMask());
+
+ MachProjNode *proj = new (matcher.C, 1) MachProjNode( n, 1, RegMask::Empty, MachProjNode::fat_proj );
+ cfg->_bbs.map(proj->_idx,this);
+ _nodes.insert(phi_cnt++, proj);
+
+ add_call_kills(proj, regs, matcher._c_reg_save_policy, false);
+ }
+
// Children are now all ready
for (DUIterator_Fast i5max, i5 = n->fast_outs(i5max); i5 < i5max; i5++) {
Node* m = n->fast_out(i5); // Get user
if( cfg->_bbs[m->_idx] != this ) continue;
if( m->is_Phi() ) continue;
+ if (m->_idx > max_idx) { // new node, skip it
+ assert(m->is_MachProj() && n->is_Mach() && n->as_Mach()->has_call(), "unexpected node types");
+ continue;
+ }
if( !--ready_cnt[m->_idx] )
worklist.push(m);
}
diff --git a/src/share/vm/opto/machnode.hpp b/src/share/vm/opto/machnode.hpp
index c44c8d0d8..566e031d1 100644
--- a/src/share/vm/opto/machnode.hpp
+++ b/src/share/vm/opto/machnode.hpp
@@ -190,6 +190,9 @@ public:
// Avoid back to back some instructions on some CPUs.
bool avoid_back_to_back() const { return (flags() & Flag_avoid_back_to_back) != 0; }
+ // instruction implemented with a call
+ bool has_call() const { return (flags() & Flag_has_call) != 0; }
+
// First index in _in[] corresponding to operand, or -1 if there is none
int operand_index(uint operand) const;
diff --git a/src/share/vm/opto/node.hpp b/src/share/vm/opto/node.hpp
index 8564a7775..e10cad472 100644
--- a/src/share/vm/opto/node.hpp
+++ b/src/share/vm/opto/node.hpp
@@ -641,7 +641,8 @@ public:
Flag_is_dead_loop_safe = Flag_is_cisc_alternate << 1,
Flag_may_be_short_branch = Flag_is_dead_loop_safe << 1,
Flag_avoid_back_to_back = Flag_may_be_short_branch << 1,
- _max_flags = (Flag_avoid_back_to_back << 1) - 1 // allow flags combination
+ Flag_has_call = Flag_avoid_back_to_back << 1,
+ _max_flags = (Flag_has_call << 1) - 1 // allow flags combination
};
private: