mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-27 10:40:29 +00:00
8231649: PPC64: Intrinsics for Math.ceil, floor, rint on Power
Reviewed-by: mdoerr, vlivanov
This commit is contained in:
parent
54be25b07b
commit
f004d45d3d
@ -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));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user