< prev index next >

src/cpu/ppc/vm/ppc.ad

Print this page

        

@@ -3077,10 +3077,21 @@
     __ ld($dst$$Register, Idisp, $mem$$base$$Register);
     // TODO PPC port __ endgroup_if_needed(_size == 12);
     __ bind(done);
   %}
 
+  enc_class enc_cmove_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{
+    // TODO: PPC port $archOpcode(ppc64Opcode_cmove);
+
+    MacroAssembler _masm(&cbuf);
+    Label done;
+    __ bso($crx$$CondRegister, done);
+    __ mffprd($dst$$Register, $src$$FloatRegister);
+    // TODO PPC port __ endgroup_if_needed(_size == 12);
+    __ bind(done);
+  %}
+
   enc_class enc_bc(flagsRegSrc crx, cmpOp cmp, Label lbl) %{
     // TODO: PPC port $archOpcode(ppc64Opcode_bc);
 
     MacroAssembler _masm(&cbuf);
     Label d;   // dummy

@@ -10076,13 +10087,40 @@
 // of java.lang.Float etc., e.g.
 //   int   floatToIntBits(float value)
 //   float intBitsToFloat(int bits)
 //
 // Notes on the implementation on ppc64:
-// We only provide rules which move between a register and a stack-location,
-// because we always have to go through memory when moving between a float
-// register and an integer register.
+// For Power7 and earlier, the rules are limited to those which move between a
+// register and a stack-location, because we always have to go through memory
+// when moving between a float register and an integer register.
+// This restriction is removed in Power8 with the introduction of the mtfprd
+// and mffprd instructions.
+
+instruct moveL2D_reg(regD dst, iRegLsrc src) %{
+  match(Set dst (MoveL2D src));
+  predicate(VM_Version::has_mtfprd());
+
+  format %{ "MTFPRD  $dst, $src" %}
+  size(4);
+  ins_encode %{
+    __ mtfprd($dst$$FloatRegister, $src$$Register);
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+instruct moveI2D_reg(regD dst, iRegIsrc src) %{
+  // no match-rule, false predicate
+  effect(DEF dst, USE src);
+  predicate(false);
+
+  format %{ "MTFPRWA $dst, $src" %}
+  size(4);
+  ins_encode %{
+    __ mtfprwa($dst$$FloatRegister, $src$$Register);
+  %}
+  ins_pipe(pipe_class_default);
+%}
 
 //---------- Chain stack slots between similar types --------
 
 // These are needed so that the rules below can match.
 

@@ -10581,10 +10619,24 @@
   size(false /* TODO: PPC PORT(InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8);
   ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) );
   ins_pipe(pipe_class_default);
 %}
 
+instruct cmovI_bso_reg(iRegIdst dst, flagsRegSrc crx, regD src) %{
+  // no match-rule, false predicate
+  effect(DEF dst, USE crx, USE src);
+  predicate(false);
+
+  ins_variable_size_depending_on_alignment(true);
+
+  format %{ "cmovI   $crx, $dst, $src" %}
+  // Worst case is branch + move + stop, no stop without scheduler.
+  size(false /* TODO: PPC PORT(InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8);
+  ins_encode( enc_cmove_bso_reg(dst, crx, src) );
+  ins_pipe(pipe_class_default);
+%}
+
 instruct cmovI_bso_stackSlotL_conLvalue0_Ex(iRegIdst dst, flagsRegSrc crx, stackSlotL mem) %{
   // no match-rule, false predicate
   effect(DEF dst, USE crx, USE mem);
   predicate(false);
 

@@ -10635,13 +10687,68 @@
     nodes->push(m1);
     nodes->push(m2);
   %}
 %}
 
+instruct cmovI_bso_reg_conLvalue0_Ex(iRegIdst dst, flagsRegSrc crx, regD src) %{
+  // no match-rule, false predicate
+  effect(DEF dst, USE crx, USE src);
+  predicate(false);
+
+  format %{ "CmovI   $dst, $crx, $src \t// postalloc expanded" %}
+  postalloc_expand %{
+    //
+    // replaces
+    //
+    //   region  dst  crx  src
+    //    \       |    |   /
+    //     dst=cmovI_bso_reg_conLvalue0
+    //
+    // with
+    //
+    //   region  dst
+    //    \       /
+    //     dst=loadConI16(0)
+    //      |
+    //      ^  region  dst  crx  src
+    //      |   \       |    |    /
+    //      dst=cmovI_bso_reg
+    //
+
+    // Create new nodes.
+    MachNode *m1 = new loadConI16Node();
+    MachNode *m2 = new cmovI_bso_regNode();
+
+    // inputs for new nodes
+    m1->add_req(n_region);
+    m2->add_req(n_region, n_crx, n_src);
+
+    // precedences for new nodes
+    m2->add_prec(m1);
+
+    // operands for new nodes
+    m1->_opnds[0] = op_dst;
+    m1->_opnds[1] = new immI16Oper(0);
+
+    m2->_opnds[0] = op_dst;
+    m2->_opnds[1] = op_crx;
+    m2->_opnds[2] = op_src;
+
+    // registers for new nodes
+    ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
+    ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
+
+    // Insert new nodes.
+    nodes->push(m1);
+    nodes->push(m2);
+  %}
+%}
+
 // Double to Int conversion, NaN is mapped to 0.
 instruct convD2I_reg_ExEx(iRegIdst dst, regD src) %{
   match(Set dst (ConvD2I src));
+  predicate(!VM_Version::has_mtfprd());
   ins_cost(DEFAULT_COST);
 
   expand %{
     regD tmpD;
     stackSlotL tmpS;

@@ -10651,10 +10758,25 @@
     moveD2L_reg_stack(tmpS, tmpD);                      // Store float to stack (speculated).
     cmovI_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check.
   %}
 %}
 
+// Double to Int conversion, NaN is mapped to 0. Special version for Power8.
+instruct convD2I_reg_mffprd_ExEx(iRegIdst dst, regD src) %{
+  match(Set dst (ConvD2I src));
+  predicate(VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regD tmpD;
+    flagsReg crx;
+    cmpDUnordered_reg_reg(crx, src, src);               // Check whether src is NaN.
+    convD2IRaw_regD(tmpD, src);                         // Convert float to int (speculated).
+    cmovI_bso_reg_conLvalue0_Ex(dst, crx, tmpD);        // Cmove based on NaN check.
+  %}
+%}
+
 instruct convF2IRaw_regF(regF dst, regF src) %{
   // no match-rule, false predicate
   effect(DEF dst, USE src);
   predicate(false);
 

@@ -10668,10 +10790,11 @@
 %}
 
 // Float to Int conversion, NaN is mapped to 0.
 instruct convF2I_regF_ExEx(iRegIdst dst, regF src) %{
   match(Set dst (ConvF2I src));
+  predicate(!VM_Version::has_mtfprd());
   ins_cost(DEFAULT_COST);
 
   expand %{
     regF tmpF;
     stackSlotL tmpS;

@@ -10681,10 +10804,25 @@
     moveF2L_reg_stack(tmpS, tmpF);                      // Store float to stack (speculated).
     cmovI_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check.
   %}
 %}
 
+// Float to Int conversion, NaN is mapped to 0. Special version for Power8.
+instruct convF2I_regF_mffprd_ExEx(iRegIdst dst, regF src) %{
+  match(Set dst (ConvF2I src));
+  predicate(VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regF tmpF;
+    flagsReg crx;
+    cmpFUnordered_reg_reg(crx, src, src);               // Check whether src is NaN.
+    convF2IRaw_regF(tmpF, src);                         // Convert float to int (speculated).
+    cmovI_bso_reg_conLvalue0_Ex(dst, crx, tmpF);        // Cmove based on NaN check.
+  %}
+%}
+
 // Convert to Long
 
 instruct convI2L_reg(iRegLdst dst, iRegIsrc src) %{
   match(Set dst (ConvI2L src));
   format %{ "EXTSW   $dst, $src \t// int->long" %}

@@ -10750,10 +10888,24 @@
   size(false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8);
   ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) );
   ins_pipe(pipe_class_default);
 %}
 
+instruct cmovL_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{
+  // no match-rule, false predicate
+  effect(DEF dst, USE crx, USE src);
+  predicate(false);
+
+  ins_variable_size_depending_on_alignment(true);
+
+  format %{ "cmovL   $crx, $dst, $src" %}
+  // Worst case is branch + move + stop, no stop without scheduler.
+  size(false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8);
+  ins_encode( enc_cmove_bso_reg(dst, crx, src) );
+  ins_pipe(pipe_class_default);
+%}
+
 instruct cmovL_bso_stackSlotL_conLvalue0_Ex(iRegLdst dst, flagsRegSrc crx, stackSlotL mem) %{
   // no match-rule, false predicate
   effect(DEF dst, USE crx, USE mem);
   predicate(false);
 

@@ -10801,13 +10953,65 @@
     nodes->push(m1);
     nodes->push(m2);
   %}
 %}
 
+instruct cmovL_bso_reg_conLvalue0_Ex(iRegLdst dst, flagsRegSrc crx, regD src) %{
+  // no match-rule, false predicate
+  effect(DEF dst, USE crx, USE src);
+  predicate(false);
+
+  format %{ "CmovL   $dst, $crx, $src \t// postalloc expanded" %}
+  postalloc_expand %{
+    //
+    // replaces
+    //
+    //   region  dst  crx  src
+    //    \       |    |   /
+    //     dst=cmovL_bso_reg_conLvalue0
+    //
+    // with
+    //
+    //   region  dst
+    //    \       /
+    //     dst=loadConL16(0)
+    //      |
+    //      ^  region  dst  crx  src
+    //      |   \       |    |    /
+    //      dst=cmovL_bso_reg
+    //
+
+    // Create new nodes.
+    MachNode *m1 = new loadConL16Node();
+    MachNode *m2 = new cmovL_bso_regNode();
+
+    // inputs for new nodes
+    m1->add_req(n_region);
+    m2->add_req(n_region, n_crx, n_src);
+    m2->add_prec(m1);
+
+    // operands for new nodes
+    m1->_opnds[0] = op_dst;
+    m1->_opnds[1] = new immL16Oper(0);
+    m2->_opnds[0] = op_dst;
+    m2->_opnds[1] = op_crx;
+    m2->_opnds[2] = op_src;
+
+    // registers for new nodes
+    ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
+    ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
+
+    // Insert new nodes.
+    nodes->push(m1);
+    nodes->push(m2);
+  %}
+%}
+
 // Float to Long conversion, NaN is mapped to 0.
 instruct convF2L_reg_ExEx(iRegLdst dst, regF src) %{
   match(Set dst (ConvF2L src));
+  predicate(!VM_Version::has_mtfprd());
   ins_cost(DEFAULT_COST);
 
   expand %{
     regF tmpF;
     stackSlotL tmpS;

@@ -10817,10 +11021,25 @@
     moveF2L_reg_stack(tmpS, tmpF);                      // Store float to stack (speculated).
     cmovL_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check.
   %}
 %}
 
+// Float to Long conversion, NaN is mapped to 0. Special version for Power8.
+instruct convF2L_reg_mffprd_ExEx(iRegLdst dst, regF src) %{
+  match(Set dst (ConvF2L src));
+  predicate(VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regF tmpF;
+    flagsReg crx;
+    cmpFUnordered_reg_reg(crx, src, src);               // Check whether src is NaN.
+    convF2LRaw_regF(tmpF, src);                         // Convert float to long (speculated).
+    cmovL_bso_reg_conLvalue0_Ex(dst, crx, tmpF);        // Cmove based on NaN check.
+  %}
+%}
+
 instruct convD2LRaw_regD(regD dst, regD src) %{
   // no match-rule, false predicate
   effect(DEF dst, USE src);
   predicate(false);
 

@@ -10834,10 +11053,11 @@
 %}
 
 // Double to Long conversion, NaN is mapped to 0.
 instruct convD2L_reg_ExEx(iRegLdst dst, regD src) %{
   match(Set dst (ConvD2L src));
+  predicate(!VM_Version::has_mtfprd());
   ins_cost(DEFAULT_COST);
 
   expand %{
     regD tmpD;
     stackSlotL tmpS;

@@ -10847,10 +11067,25 @@
     moveD2L_reg_stack(tmpS, tmpD);                      // Store float to stack (speculated).
     cmovL_bso_stackSlotL_conLvalue0_Ex(dst, crx, tmpS); // Cmove based on NaN check.
   %}
 %}
 
+// Double to Long conversion, NaN is mapped to 0. Special version for Power8.
+instruct convD2L_reg_mffprd_ExEx(iRegLdst dst, regD src) %{
+  match(Set dst (ConvD2L src));
+  predicate(VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regD tmpD;
+    flagsReg crx;
+    cmpDUnordered_reg_reg(crx, src, src);               // Check whether src is NaN.
+    convD2LRaw_regD(tmpD, src);                         // Convert float to long (speculated).
+    cmovL_bso_reg_conLvalue0_Ex(dst, crx, tmpD);        // Cmove based on NaN check.
+  %}
+%}
+
 // Convert to Float
 
 // Placed here as needed in expand.
 instruct convL2DRaw_regD(regD dst, regD src) %{
   // no match-rule, false predicate

@@ -10912,11 +11147,11 @@
 %}
 
 // Integer to Float conversion. Special version for Power7.
 instruct convI2F_ireg_fcfids_Ex(regF dst, iRegIsrc src) %{
   match(Set dst (ConvI2F src));
-  predicate(VM_Version::has_fcfids());
+  predicate(VM_Version::has_fcfids() && !VM_Version::has_mtfprd());
   ins_cost(DEFAULT_COST);
 
   expand %{
     iRegLdst tmpL;
     stackSlotL tmpS;

@@ -10926,14 +11161,27 @@
     moveL2D_stack_reg(tmpD, tmpS);       // Load long into double register.
     convL2FRaw_regF(dst, tmpD);          // Convert to float.
   %}
 %}
 
+// Integer to Float conversion. Special version for Power8.
+instruct convI2F_ireg_mtfprd_Ex(regF dst, iRegIsrc src) %{
+  match(Set dst (ConvI2F src));
+  predicate(VM_Version::has_fcfids() && VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regD tmpD;
+    moveI2D_reg(tmpD, src);
+    convL2FRaw_regF(dst, tmpD);          // Convert to float.
+  %}
+%}
+
 // L2F to avoid runtime call.
 instruct convL2F_ireg_fcfids_Ex(regF dst, iRegLsrc src) %{
   match(Set dst (ConvL2F src));
-  predicate(VM_Version::has_fcfids());
+  predicate(VM_Version::has_fcfids() && !VM_Version::has_mtfprd());
   ins_cost(DEFAULT_COST);
 
   expand %{
     stackSlotL tmpS;
     regD tmpD;

@@ -10941,18 +11189,32 @@
     moveL2D_stack_reg(tmpD, tmpS);       // Load long into double register.
     convL2FRaw_regF(dst, tmpD);          // Convert to float.
   %}
 %}
 
+// L2F to avoid runtime call.  Special version for Power8.
+instruct convL2F_ireg_mtfprd_Ex(regF dst, iRegLsrc src) %{
+  match(Set dst (ConvL2F src));
+  predicate(VM_Version::has_fcfids() && VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regD tmpD;
+    moveL2D_reg(tmpD, src);
+    convL2FRaw_regF(dst, tmpD);          // Convert to float.
+  %}
+%}
+
 // Moved up as used in expand.
 //instruct convD2F_reg(regF dst, regD src) %{%}
 
 // Convert to Double
 
 // Integer to Double conversion.
 instruct convI2D_reg_Ex(regD dst, iRegIsrc src) %{
   match(Set dst (ConvI2D src));
+  predicate(!VM_Version::has_mtfprd());
   ins_cost(DEFAULT_COST);
 
   expand %{
     iRegLdst tmpL;
     stackSlotL tmpS;

@@ -10962,10 +11224,23 @@
     moveL2D_stack_reg(tmpD, tmpS);       // Load long into double register.
     convL2DRaw_regD(dst, tmpD);          // Convert to double.
   %}
 %}
 
+// Integer to Double conversion. Special version for Power8.
+instruct convI2D_reg_mtfprd_Ex(regD dst, iRegIsrc src) %{
+  match(Set dst (ConvI2D src));
+  predicate(VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regD tmpD;
+    moveI2D_reg(tmpD, src);
+    convL2DRaw_regD(dst, tmpD);          // Convert to double.
+  %}
+%}
+
 // Long to Double conversion
 instruct convL2D_reg_Ex(regD dst, stackSlotL src) %{
   match(Set dst (ConvL2D src));
   ins_cost(DEFAULT_COST + MEMORY_REF_COST);
 

@@ -10974,10 +11249,23 @@
     moveL2D_stack_reg(tmpD, src);
     convL2DRaw_regD(dst, tmpD);
   %}
 %}
 
+// Long to Double conversion. Special version for Power8.
+instruct convL2D_reg_mtfprd_Ex(regD dst, iRegLsrc src) %{
+  match(Set dst (ConvL2D src));
+  predicate(VM_Version::has_mtfprd());
+  ins_cost(DEFAULT_COST);
+
+  expand %{
+    regD tmpD;
+    moveL2D_reg(tmpD, src);
+    convL2DRaw_regD(dst, tmpD);          // Convert to double.
+  %}
+%}
+
 instruct convF2D_reg(regD dst, regF src) %{
   match(Set dst (ConvF2D src));
   format %{ "FMR     $dst, $src \t// float->double" %}
   // variable size, 0 or 4
   ins_encode %{
< prev index next >