# HG changeset patch # User mhorie # Date 1571797605 18000 # Node ID 70e6b0d8db13ddcf657d57756910922423be9aa1 # Parent c9c3bb79861e0dafae08dc56ab1de4efb3742771 8231649: PPC64: Intrinsics for Math.ceil, floor, rint on Power Reviewed-by: mdoerr, vlivanov diff -r c9c3bb79861e -r 70e6b0d8db13 src/hotspot/cpu/ppc/assembler_ppc.hpp --- 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); diff -r c9c3bb79861e -r 70e6b0d8db13 src/hotspot/cpu/ppc/assembler_ppc.inline.hpp --- 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)); } diff -r c9c3bb79861e -r 70e6b0d8db13 src/hotspot/cpu/ppc/ppc.ad --- 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) %{ diff -r c9c3bb79861e -r 70e6b0d8db13 src/hotspot/share/opto/convertnode.cpp --- 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) { diff -r c9c3bb79861e -r 70e6b0d8db13 src/hotspot/share/opto/convertnode.hpp --- 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; } diff -r c9c3bb79861e -r 70e6b0d8db13 src/hotspot/share/opto/library_call.cpp --- 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));