8231649: PPC64: Intrinsics for Math.ceil, floor, rint on Power
authormhorie
Tue, 22 Oct 2019 21:26:45 -0500
changeset 58745 70e6b0d8db13
parent 58744 c9c3bb79861e
child 58746 a3d208fc1b10
8231649: PPC64: Intrinsics for Math.ceil, floor, rint on Power Reviewed-by: mdoerr, vlivanov
src/hotspot/cpu/ppc/assembler_ppc.hpp
src/hotspot/cpu/ppc/assembler_ppc.inline.hpp
src/hotspot/cpu/ppc/ppc.ad
src/hotspot/share/opto/convertnode.cpp
src/hotspot/share/opto/convertnode.hpp
src/hotspot/share/opto/library_call.cpp
--- a/src/hotspot/cpu/ppc/assembler_ppc.hpp	Tue Oct 22 22:00:21 2019 -0400
+++ b/src/hotspot/cpu/ppc/assembler_ppc.hpp	Tue Oct 22 21:26:45 2019 -0500
@@ -444,6 +444,9 @@
     FDIV_OPCODE   = (63u << OPCODE_SHIFT |  18u << 1),
     FDIVS_OPCODE  = (59u << OPCODE_SHIFT |  18u << 1),
     FMR_OPCODE    = (63u << OPCODE_SHIFT |  72u << 1),
+    FRIN_OPCODE   = (63u << OPCODE_SHIFT | 392u << 1),
+    FRIP_OPCODE   = (63u << OPCODE_SHIFT | 456u << 1),
+    FRIM_OPCODE   = (63u << OPCODE_SHIFT | 488u << 1),
     // These are special Power6 opcodes, reused for "lfdepx" and "stfdepx"
     // on Power7.  Do not use.
     // MFFGPR_OPCODE  = (31u << OPCODE_SHIFT | 607u << 1),
@@ -545,6 +548,9 @@
     XVMSUBADP_OPCODE=(60u << OPCODE_SHIFT |  113u << 3),
     XVNMSUBASP_OPCODE=(60u<< OPCODE_SHIFT |  209u << 3),
     XVNMSUBADP_OPCODE=(60u<< OPCODE_SHIFT |  241u << 3),
+    XVRDPI_OPCODE  = (60u << OPCODE_SHIFT |  201u << 2),
+    XVRDPIM_OPCODE = (60u << OPCODE_SHIFT |  249u << 2),
+    XVRDPIP_OPCODE = (60u << OPCODE_SHIFT |  233u << 2),
 
     // Deliver A Random Number (introduced with POWER9)
     DARN_OPCODE    = (31u << OPCODE_SHIFT |  755u << 1),
@@ -1981,6 +1987,10 @@
   inline void fmr(  FloatRegister d, FloatRegister b);
   inline void fmr_( FloatRegister d, FloatRegister b);
 
+  inline void frin( FloatRegister d, FloatRegister b);
+  inline void frip( FloatRegister d, FloatRegister b);
+  inline void frim( FloatRegister d, FloatRegister b);
+
   //  inline void mffgpr( FloatRegister d, Register b);
   //  inline void mftgpr( Register d, FloatRegister b);
   inline void cmpb(   Register a, Register s, Register b);
@@ -2241,6 +2251,9 @@
   inline void xvmsubadp(VectorSRegister d, VectorSRegister a, VectorSRegister b);
   inline void xvnmsubasp(VectorSRegister d, VectorSRegister a, VectorSRegister b);
   inline void xvnmsubadp(VectorSRegister d, VectorSRegister a, VectorSRegister b);
+  inline void xvrdpi(   VectorSRegister d, VectorSRegister b);
+  inline void xvrdpim(  VectorSRegister d, VectorSRegister b);
+  inline void xvrdpip(  VectorSRegister d, VectorSRegister b);
 
   // VSX Extended Mnemonics
   inline void xxspltd(  VectorSRegister d, VectorSRegister a, int x);
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp	Tue Oct 22 22:00:21 2019 -0400
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp	Tue Oct 22 21:26:45 2019 -0500
@@ -675,6 +675,10 @@
 inline void Assembler::fmr( FloatRegister d, FloatRegister b) { emit_int32( FMR_OPCODE | frt(d) | frb(b) | rc(0)); }
 inline void Assembler::fmr_(FloatRegister d, FloatRegister b) { emit_int32( FMR_OPCODE | frt(d) | frb(b) | rc(1)); }
 
+inline void Assembler::frin( FloatRegister d, FloatRegister b) { emit_int32( FRIN_OPCODE | frt(d) | frb(b) | rc(0)); }
+inline void Assembler::frip( FloatRegister d, FloatRegister b) { emit_int32( FRIP_OPCODE | frt(d) | frb(b) | rc(0)); }
+inline void Assembler::frim( FloatRegister d, FloatRegister b) { emit_int32( FRIM_OPCODE | frt(d) | frb(b) | rc(0)); }
+
 // These are special Power6 opcodes, reused for "lfdepx" and "stfdepx"
 // on Power7.  Do not use.
 //inline void Assembler::mffgpr( FloatRegister d, Register b)   { emit_int32( MFFGPR_OPCODE | frt(d) | rb(b) | rc(0)); }
@@ -796,6 +800,10 @@
 inline void Assembler::xvmsubadp( VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XVMSUBADP_OPCODE  | vsrt(d) | vsra(a) | vsrb(b)); }
 inline void Assembler::xvnmsubasp(VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XVNMSUBASP_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
 inline void Assembler::xvnmsubadp(VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XVNMSUBADP_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); }
+inline void Assembler::xvrdpi(    VectorSRegister d, VectorSRegister b)                  { emit_int32( XVRDPI_OPCODE  | vsrt(d) | vsrb(b)); }
+inline void Assembler::xvrdpim(   VectorSRegister d, VectorSRegister b)                  { emit_int32( XVRDPIM_OPCODE | vsrt(d) | vsrb(b)); }
+inline void Assembler::xvrdpip(   VectorSRegister d, VectorSRegister b)                  { emit_int32( XVRDPIP_OPCODE | vsrt(d) | vsrb(b)); }
+
 inline void Assembler::mtvrd(   VectorRegister d, Register a)               { emit_int32( MTVSRD_OPCODE  | vsrt(d->to_vsr()) | ra(a)); }
 inline void Assembler::mfvrd(   Register        a, VectorRegister d)         { emit_int32( MFVSRD_OPCODE  | vsrt(d->to_vsr()) | ra(a)); }
 inline void Assembler::mtvrwz(  VectorRegister  d, Register a)               { emit_int32( MTVSRWZ_OPCODE | vsrt(d->to_vsr()) | ra(a)); }
--- a/src/hotspot/cpu/ppc/ppc.ad	Tue Oct 22 22:00:21 2019 -0400
+++ b/src/hotspot/cpu/ppc/ppc.ad	Tue Oct 22 21:26:45 2019 -0500
@@ -972,6 +972,8 @@
   // To keep related declarations/definitions/uses close together,
   // we switch between source %{ }% and source_hpp %{ }% freely as needed.
 
+#include "opto/convertnode.hpp"
+
   // Returns true if Node n is followed by a MemBar node that
   // will do an acquire. If so, this node must not do the acquire
   // operation.
@@ -2272,6 +2274,7 @@
   case Op_AddVL:
   case Op_SubVL:
   case Op_MulVI:
+  case Op_RoundDoubleModeV:
     return SuperwordUseVSX;
   case Op_PopCountVI:
     return (SuperwordUseVSX && UsePopCountInstruction);
@@ -14454,6 +14457,53 @@
   ins_pipe(pipe_class_default);
 %}
 
+// Round Instructions
+instruct roundD_reg(regD dst, regD src, immI8 rmode) %{
+  match(Set dst (RoundDoubleMode src rmode));
+  format %{ "RoundDoubleMode $src,$rmode" %}
+  size(4);
+  ins_encode %{
+    switch ($rmode$$constant) {
+      case RoundDoubleModeNode::rmode_rint:
+        __ frin($dst$$FloatRegister, $src$$FloatRegister);
+        break;
+      case RoundDoubleModeNode::rmode_floor:
+        __ frim($dst$$FloatRegister, $src$$FloatRegister);
+        break;
+      case RoundDoubleModeNode::rmode_ceil:
+        __ frip($dst$$FloatRegister, $src$$FloatRegister);
+        break;
+      default:
+        ShouldNotReachHere();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
+// Vector Round Instructions
+instruct vround2D_reg(vecX dst, vecX src, immI8 rmode) %{
+  match(Set dst (RoundDoubleModeV src rmode));
+  predicate(n->as_Vector()->length() == 2);
+  format %{ "RoundDoubleModeV $src,$rmode" %}
+  size(4);
+  ins_encode %{
+    switch ($rmode$$constant) {
+      case RoundDoubleModeNode::rmode_rint:
+        __ xvrdpi($dst$$VectorSRegister, $src$$VectorSRegister);
+        break;
+      case RoundDoubleModeNode::rmode_floor:
+        __ xvrdpim($dst$$VectorSRegister, $src$$VectorSRegister);
+        break;
+      case RoundDoubleModeNode::rmode_ceil:
+        __ xvrdpip($dst$$VectorSRegister, $src$$VectorSRegister);
+        break;
+      default:
+        ShouldNotReachHere();
+    }
+  %}
+  ins_pipe(pipe_class_default);
+%}
+
 // Vector Negate Instructions
 
 instruct vneg4F_reg(vecX dst, vecX src) %{
--- a/src/hotspot/share/opto/convertnode.cpp	Tue Oct 22 22:00:21 2019 -0400
+++ b/src/hotspot/share/opto/convertnode.cpp	Tue Oct 22 21:26:45 2019 -0500
@@ -532,6 +532,11 @@
 }
 
 //=============================================================================
+RoundDoubleModeNode* RoundDoubleModeNode::make(PhaseGVN& gvn, Node* arg, RoundDoubleModeNode::RoundingMode rmode) {
+  ConINode* rm = gvn.intcon(rmode);
+  return new RoundDoubleModeNode(arg, (Node *)rm);
+}
+
 //------------------------------Identity---------------------------------------
 // Remove redundant roundings.
 Node* RoundDoubleModeNode::Identity(PhaseGVN* phase) {
--- a/src/hotspot/share/opto/convertnode.hpp	Tue Oct 22 22:00:21 2019 -0400
+++ b/src/hotspot/share/opto/convertnode.hpp	Tue Oct 22 21:26:45 2019 -0500
@@ -215,7 +215,13 @@
 //-----------------------------RoundDoubleModeNode-----------------------------
 class RoundDoubleModeNode: public Node {
   public:
+  enum RoundingMode {
+    rmode_rint  = 0,
+    rmode_floor = 1,
+    rmode_ceil  = 2
+  };
   RoundDoubleModeNode(Node *in1, Node * rmode): Node(0, in1, rmode) {}
+  static RoundDoubleModeNode* make(PhaseGVN& gvn, Node* arg, RoundDoubleModeNode::RoundingMode rmode);
   virtual int   Opcode() const;
   virtual const Type *bottom_type() const { return Type::DOUBLE; }
   virtual uint  ideal_reg() const { return Op_RegD; }
--- a/src/hotspot/share/opto/library_call.cpp	Tue Oct 22 22:00:21 2019 -0400
+++ b/src/hotspot/share/opto/library_call.cpp	Tue Oct 22 21:26:45 2019 -0500
@@ -1822,9 +1822,9 @@
   switch (id) {
   case vmIntrinsics::_dabs:   n = new AbsDNode(                arg);  break;
   case vmIntrinsics::_dsqrt:  n = new SqrtDNode(C, control(),  arg);  break;
-  case vmIntrinsics::_ceil:   n = new RoundDoubleModeNode(arg, makecon(TypeInt::make(2))); break;
-  case vmIntrinsics::_floor:  n = new RoundDoubleModeNode(arg, makecon(TypeInt::make(1))); break;
-  case vmIntrinsics::_rint:   n = new RoundDoubleModeNode(arg, makecon(TypeInt::make(0))); break;
+  case vmIntrinsics::_ceil:   n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_ceil); break;
+  case vmIntrinsics::_floor:  n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_floor); break;
+  case vmIntrinsics::_rint:   n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_rint); break;
   default:  fatal_unexpected_iid(id);  break;
   }
   set_result(_gvn.transform(n));