Skip to content
Permalink
Browse files

8231649: PPC64: Intrinsics for Math.ceil, floor, rint on Power

Reviewed-by: mdoerr, vlivanov
  • Loading branch information
Michihiro Horie
Michihiro Horie committed Oct 23, 2019
1 parent 54be25b commit f004d45d3db310f5ce25bbcc416c90eb1eb574d4
@@ -444,6 +444,9 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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 @@ class Assembler : public AbstractAssembler {
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);
@@ -675,6 +675,10 @@ inline void Assembler::stfdx(FloatRegister s, Register a, Register b){ emit_int3
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::xvmsubasp( VectorSRegister d, VectorSRegister a, VectorSR
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)); }
@@ -972,6 +972,8 @@ source_hpp %{
// 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 @@ const bool Matcher::match_rule_supported(int opcode) {
case Op_AddVL:
case Op_SubVL:
case Op_MulVI:
case Op_RoundDoubleModeV:
return SuperwordUseVSX;
case Op_PopCountVI:
return (SuperwordUseVSX && UsePopCountInstruction);
@@ -14454,6 +14457,53 @@ instruct vabs2D_reg(vecX dst, vecX src) %{
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) %{
@@ -532,6 +532,11 @@ const Type* RoundDoubleNode::Value(PhaseGVN* phase) const {
}

//=============================================================================
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) {
@@ -215,7 +215,13 @@ class RoundDoubleNode: public Node {
//-----------------------------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; }
@@ -1822,9 +1822,9 @@ bool LibraryCallKit::inline_double_math(vmIntrinsics::ID id) {
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));

0 comments on commit f004d45

Please sign in to comment.
You can’t perform that action at this time.