8028580: PPC64 (part 114/120): Support for Call nodes with constants.
authorgoetz
Wed, 20 Nov 2013 11:08:09 -0800
changeset 22850 4e69ce7e1101
parent 22849 b8670e920530
child 22851 4c4b6a45be43
8028580: PPC64 (part 114/120): Support for Call nodes with constants. Summary: extends MachCall nodes so that they can issue constants to the constant table Reviewed-by: kvn
hotspot/src/share/vm/adlc/adlparse.cpp
hotspot/src/share/vm/adlc/formssel.cpp
hotspot/src/share/vm/adlc/formssel.hpp
hotspot/src/share/vm/adlc/output_c.cpp
hotspot/src/share/vm/adlc/output_h.cpp
hotspot/src/share/vm/opto/machnode.cpp
hotspot/src/share/vm/opto/machnode.hpp
hotspot/src/share/vm/opto/output.cpp
--- a/hotspot/src/share/vm/adlc/adlparse.cpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/adlc/adlparse.cpp	Wed Nov 20 11:08:09 2013 -0800
@@ -2863,7 +2863,10 @@
       // Check if this instruct is a MachConstantNode.
       if (strcmp(rep_var, "constanttablebase") == 0) {
         // This instruct is a MachConstantNode.
-        inst.set_is_mach_constant(true);
+        inst.set_needs_constant_base(true);
+        if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) {
+          inst.set_is_mach_constant(true);
+        }
 
         if (_curchar == '(')  {
           parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument "
@@ -2965,18 +2968,34 @@
       while (_curchar != ')') {
         char *param = get_ident_or_literal_constant("encoding operand");
         if ( param != NULL ) {
-          // Found a parameter:
-          // Check it is a local name, add it to the list, then check for more
-          // New: allow hex constants as parameters to an encode method.
-          // New: allow parenthesized expressions as parameters.
-          // New: allow "primary", "secondary", "tertiary" as parameters.
-          // New: allow user-defined register name as parameter
-          if ( (inst._localNames[param] == NULL) &&
-               !ADLParser::is_literal_constant(param) &&
-               (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
-               ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
-            parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
-            return;
+
+          // Check if this instruct is a MachConstantNode.
+          if (strcmp(param, "constanttablebase") == 0) {
+            // This instruct is a MachConstantNode.
+            inst.set_needs_constant_base(true);
+            if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) {
+              inst.set_is_mach_constant(true);
+            }
+
+            if (_curchar == '(')  {
+              parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument "
+                        "(only constantaddress and constantoffset)", ec_name);
+              return;
+            }
+          } else {
+            // Found a parameter:
+            // Check it is a local name, add it to the list, then check for more
+            // New: allow hex constants as parameters to an encode method.
+            // New: allow parenthesized expressions as parameters.
+            // New: allow "primary", "secondary", "tertiary" as parameters.
+            // New: allow user-defined register name as parameter
+            if ( (inst._localNames[param] == NULL) &&
+                 !ADLParser::is_literal_constant(param) &&
+                 (Opcode::as_opcode_type(param) == Opcode::NOT_AN_OPCODE) &&
+                 ((_AD._register == NULL ) || (_AD._register->getRegDef(param) == NULL)) ) {
+              parse_err(SYNERR, "Using non-locally defined parameter %s for encoding %s.\n", param, ec_name);
+              return;
+            }
           }
           params->add_entry(param);
 
@@ -3122,7 +3141,10 @@
           // Check if this instruct is a MachConstantNode.
           if (strcmp(param, "constanttablebase") == 0) {
             // This instruct is a MachConstantNode.
-            inst.set_is_mach_constant(true);
+            inst.set_needs_constant_base(true);
+            if (strncmp("MachCall", inst.mach_base_class(_globalNames), strlen("MachCall")) != 0 ) {
+              inst.set_is_mach_constant(true);
+            }
 
             if (_curchar == '(') {
               parse_err(SYNERR, "constanttablebase in instruct %s cannot have an argument "
--- a/hotspot/src/share/vm/adlc/formssel.cpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.cpp	Wed Nov 20 11:08:09 2013 -0800
@@ -32,6 +32,7 @@
     _localNames(cmpstr, hashstr, Form::arena),
     _effects(cmpstr, hashstr, Form::arena),
     _is_mach_constant(false),
+    _needs_constant_base(false),
     _has_call(false)
 {
       _ftype = Form::INS;
@@ -65,6 +66,7 @@
     _localNames(instr->_localNames),
     _effects(instr->_effects),
     _is_mach_constant(false),
+    _needs_constant_base(false),
     _has_call(false)
 {
       _ftype = Form::INS;
--- a/hotspot/src/share/vm/adlc/formssel.hpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/adlc/formssel.hpp	Wed Nov 20 11:08:09 2013 -0800
@@ -83,7 +83,8 @@
   const char    *_cisc_reg_mask_name;
   InstructForm  *_short_branch_form;
   bool           _is_short_branch;
-  bool           _is_mach_constant;   // true if Node is a MachConstantNode
+  bool           _is_mach_constant;    // True if Node is a MachConstantNode.
+  bool           _needs_constant_base; // True if Node needs the mach_constant_base input.
   uint           _alignment;
 
 public:
@@ -262,6 +263,8 @@
 
   bool                    is_mach_constant() const { return _is_mach_constant;     }
   void                set_is_mach_constant(bool x) {        _is_mach_constant = x; }
+  bool                    needs_constant_base() const { return _needs_constant_base;     }
+  void                set_needs_constant_base(bool x) {        _needs_constant_base = x; }
 
   InstructForm       *short_branch_form() { return _short_branch_form; }
   bool                has_short_branch_form() { return _short_branch_form != NULL; }
--- a/hotspot/src/share/vm/adlc/output_c.cpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/adlc/output_c.cpp	Wed Nov 20 11:08:09 2013 -0800
@@ -1839,7 +1839,9 @@
 
   // If the node is a MachConstantNode, insert the MachConstantBaseNode edge.
   // NOTE: this edge must be the last input (see MachConstantNode::mach_constant_base_node_input).
-  if (node->is_mach_constant()) {
+  // There are nodes that don't use $constantablebase, but still require that it
+  // is an input to the node. Example: divF_reg_immN, Repl32B_imm on x86_64.
+  if (node->is_mach_constant() || node->needs_constant_base()) {
     fprintf(fp,"  add_req(C->mach_constant_base_node());\n");
   }
 
@@ -1952,9 +1954,9 @@
       else if ((strcmp(rep_var, "constanttablebase") == 0) ||
                (strcmp(rep_var, "constantoffset")    == 0) ||
                (strcmp(rep_var, "constantaddress")   == 0)) {
-        if (!_inst.is_mach_constant()) {
+        if (!(_inst.is_mach_constant() || _inst.needs_constant_base())) {
           _AD.syntax_err(_encoding._linenum,
-                         "Replacement variable %s not allowed in instruct %s (only in MachConstantNode).\n",
+                         "Replacement variable %s not allowed in instruct %s (only in MachConstantNode or MachCall).\n",
                          rep_var, _encoding._name);
         }
       }
@@ -3182,6 +3184,7 @@
     if( instr->expands() || instr->needs_projections() ||
         instr->has_temps() ||
         instr->is_mach_constant() ||
+        instr->needs_constant_base() ||
         instr->_matrule != NULL &&
         instr->num_opnds() != instr->num_unique_opnds() )
       defineExpand(_CPP_EXPAND_file._fp, instr);
@@ -3954,8 +3957,10 @@
   }
 
   // Fill in the bottom_type where requested
-  if ( inst->captures_bottom_type(_globalNames) ) {
-    fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent);
+  if (inst->captures_bottom_type(_globalNames)) {
+    if (strncmp("MachCall", inst->mach_base_class(_globalNames), strlen("MachCall"))) {
+      fprintf(fp_cpp, "%s node->_bottom_type = _leaf->bottom_type();\n", indent);
+    }
   }
   if( inst->is_ideal_if() ) {
     fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent);
--- a/hotspot/src/share/vm/adlc/output_h.cpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/adlc/output_h.cpp	Wed Nov 20 11:08:09 2013 -0800
@@ -1614,7 +1614,7 @@
       if (strcmp (attr->_ident,"ins_cost") &&
           strncmp(attr->_ident,"ins_field_", 10) != 0 &&
           strcmp (attr->_ident,"ins_short_branch")) {
-        fprintf(fp,"          int            %s() const { return %s; }\n",
+        fprintf(fp,"  virtual int            %s() const { return %s; }\n",
                 attr->_ident, attr->_val);
       }
       // Check value for ins_avoid_back_to_back, and if it is true (1), set the flag
@@ -1655,6 +1655,11 @@
             instr->ideal_Opcode(_globalNames) );
     }
 
+    if (instr->needs_constant_base() &&
+        !instr->is_mach_constant()) {  // These inherit the funcion from MachConstantNode.
+      fprintf(fp,"  virtual uint           mach_constant_base_node_input() const { return req()-1; }\n");
+    }
+
     // Allow machine-independent optimization, invert the sense of the IF test
     if( instr->is_ideal_if() ) {
       fprintf(fp,"  virtual void           negate() { \n");
@@ -1823,6 +1828,7 @@
     if( instr->expands() || instr->needs_projections() ||
         instr->has_temps() ||
         instr->is_mach_constant() ||
+        instr->needs_constant_base() ||
         instr->_matrule != NULL &&
         instr->num_opnds() != instr->num_unique_opnds() ) {
       fprintf(fp,"  virtual MachNode      *Expand(State *state, Node_List &proj_list, Node* mem);\n");
--- a/hotspot/src/share/vm/opto/machnode.cpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/opto/machnode.cpp	Wed Nov 20 11:08:09 2013 -0800
@@ -648,10 +648,15 @@
 
 
 //------------------------------Registers--------------------------------------
-const RegMask &MachCallNode::in_RegMask( uint idx ) const {
+const RegMask &MachCallNode::in_RegMask(uint idx) const {
   // Values in the domain use the users calling convention, embodied in the
   // _in_rms array of RegMasks.
-  if (idx < tf()->domain()->cnt())  return _in_rms[idx];
+  if (idx < tf()->domain()->cnt()) {
+    return _in_rms[idx];
+  }
+  if (idx == mach_constant_base_node_input()) {
+    return MachConstantBaseNode::static_out_RegMask();
+  }
   // Values outside the domain represent debug info
   return *Compile::current()->matcher()->idealreg2debugmask[in(idx)->ideal_reg()];
 }
@@ -678,7 +683,12 @@
 const RegMask &MachCallJavaNode::in_RegMask(uint idx) const {
   // Values in the domain use the users calling convention, embodied in the
   // _in_rms array of RegMasks.
-  if (idx < tf()->domain()->cnt())  return _in_rms[idx];
+  if (idx < tf()->domain()->cnt()) {
+    return _in_rms[idx];
+  }
+  if (idx == mach_constant_base_node_input()) {
+    return MachConstantBaseNode::static_out_RegMask();
+  }
   // Values outside the domain represent debug info
   Matcher* m = Compile::current()->matcher();
   // If this call is a MethodHandle invoke we have to use a different
--- a/hotspot/src/share/vm/opto/machnode.hpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/opto/machnode.hpp	Wed Nov 20 11:08:09 2013 -0800
@@ -181,6 +181,9 @@
   // Number of inputs which come before the first operand.
   // Generally at least 1, to skip the Control input
   virtual uint oper_input_base() const { return 1; }
+  // Position of constant base node in node's inputs. -1 if
+  // no constant base node input.
+  virtual uint mach_constant_base_node_input() const { return (uint)-1; }
 
   // Copy inputs and operands to new node of instruction.
   // Called from cisc_version() and short_branch_version().
@@ -250,6 +253,9 @@
   // Return number of relocatable values contained in this instruction
   virtual int   reloc() const { return 0; }
 
+  // Return number of words used for double constants in this instruction
+  virtual int   ins_num_consts() const { return 0; }
+
   // Hash and compare over operands.  Used to do GVN on machine Nodes.
   virtual uint  hash() const;
   virtual uint  cmp( const Node &n ) const;
@@ -412,7 +418,7 @@
   }
 
   // Input edge of MachConstantBaseNode.
-  uint mach_constant_base_node_input() const { return req() - 1; }
+  virtual uint mach_constant_base_node_input() const { return req() - 1; }
 
   int  constant_offset();
   int  constant_offset() const { return ((MachConstantNode*) this)->constant_offset(); }
--- a/hotspot/src/share/vm/opto/output.cpp	Tue Nov 19 11:53:58 2013 -0800
+++ b/hotspot/src/share/vm/opto/output.cpp	Wed Nov 20 11:08:09 2013 -0800
@@ -1083,6 +1083,7 @@
   assert(_frame_slots >= 0 && _frame_slots < 1000000, "sanity check");
 
   if (has_mach_constant_base_node()) {
+    uint add_size = 0;
     // Fill the constant table.
     // Note:  This must happen before shorten_branches.
     for (uint i = 0; i < _cfg->number_of_blocks(); i++) {
@@ -1096,6 +1097,9 @@
         if (n->is_MachConstant()) {
           MachConstantNode* machcon = n->as_MachConstant();
           machcon->eval_constant(C);
+        } else if (n->is_Mach()) {
+          // On Power there are more nodes that issue constants.
+          add_size += (n->as_Mach()->ins_num_consts() * 8);
         }
       }
     }
@@ -1103,7 +1107,7 @@
     // Calculate the offsets of the constants and the size of the
     // constant table (including the padding to the next section).
     constant_table().calculate_offsets_and_size();
-    const_req = constant_table().size();
+    const_req = constant_table().size() + add_size;
   }
 
   // Initialize the space for the BufferBlob used to find and verify
@@ -1374,7 +1378,7 @@
             int offset = blk_starts[block_num] - current_offset;
             if (block_num >= i) {
               // Current and following block's offset are not
-              // finilized yet, adjust distance by the difference
+              // finalized yet, adjust distance by the difference
               // between calculated and final offsets of current block.
               offset -= (blk_starts[i] - blk_offset);
             }