8171244: PPC64: Make interpreter's math entries consistent with C1 and C2 and support FMA

Reviewed-by: kvn, goetz
This commit is contained in:
Martin Doerr 2016-12-15 14:24:04 +01:00
parent d652c70de6
commit c44e860576
9 changed files with 301 additions and 53 deletions

View File

@ -51,19 +51,25 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) {
return i;
}
// Support abs and sqrt like in compiler.
// For others we can use a normal (native) entry.
bool AbstractInterpreter::math_entry_available(AbstractInterpreter::MethodKind kind) {
if (!InlineIntrinsics) return false;
return ((kind==Interpreter::java_lang_math_sqrt && VM_Version::has_fsqrt()) ||
(kind==Interpreter::java_lang_math_abs));
}
// These should never be compiled since the interpreter will prefer
// the compiled version to the intrinsic version.
bool AbstractInterpreter::can_be_compiled(methodHandle m) {
return !math_entry_available(method_kind(m));
switch (method_kind(m)) {
case Interpreter::java_lang_math_sin : // fall thru
case Interpreter::java_lang_math_cos : // fall thru
case Interpreter::java_lang_math_tan : // fall thru
case Interpreter::java_lang_math_abs : // fall thru
case Interpreter::java_lang_math_log : // fall thru
case Interpreter::java_lang_math_log10 : // fall thru
case Interpreter::java_lang_math_sqrt : // fall thru
case Interpreter::java_lang_math_pow : // fall thru
case Interpreter::java_lang_math_exp : // fall thru
case Interpreter::java_lang_math_fmaD : // fall thru
case Interpreter::java_lang_math_fmaF :
return false;
default:
return true;
}
}
// How much stack a method activation needs in stack slots.

View File

@ -460,16 +460,15 @@ class Assembler : public AbstractAssembler {
FCTIWZ_OPCODE = (63u << OPCODE_SHIFT | 15u << 1),
FRSP_OPCODE = (63u << OPCODE_SHIFT | 12u << 1),
// WARNING: using fmadd results in a non-compliant vm. Some floating
// point tck tests will fail.
FMADD_OPCODE = (59u << OPCODE_SHIFT | 29u << 1),
DMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1),
FMSUB_OPCODE = (59u << OPCODE_SHIFT | 28u << 1),
DMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1),
FNMADD_OPCODE = (59u << OPCODE_SHIFT | 31u << 1),
DNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1),
FNMSUB_OPCODE = (59u << OPCODE_SHIFT | 30u << 1),
DNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1),
// Fused multiply-accumulate instructions.
FMADD_OPCODE = (63u << OPCODE_SHIFT | 29u << 1),
FMADDS_OPCODE = (59u << OPCODE_SHIFT | 29u << 1),
FMSUB_OPCODE = (63u << OPCODE_SHIFT | 28u << 1),
FMSUBS_OPCODE = (59u << OPCODE_SHIFT | 28u << 1),
FNMADD_OPCODE = (63u << OPCODE_SHIFT | 31u << 1),
FNMADDS_OPCODE = (59u << OPCODE_SHIFT | 31u << 1),
FNMSUB_OPCODE = (63u << OPCODE_SHIFT | 30u << 1),
FNMSUBS_OPCODE = (59u << OPCODE_SHIFT | 30u << 1),
LFD_OPCODE = (50u << OPCODE_SHIFT | 00u << 1),
LFDU_OPCODE = (51u << OPCODE_SHIFT | 00u << 1),
@ -1939,6 +1938,26 @@ class Assembler : public AbstractAssembler {
inline void fdivs( FloatRegister d, FloatRegister a, FloatRegister b);
inline void fdivs_(FloatRegister d, FloatRegister a, FloatRegister b);
// Fused multiply-accumulate instructions.
// WARNING: Use only when rounding between the 2 parts is not desired.
// Some floating point tck tests will fail if used incorrectly.
inline void fmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fmadds_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fmsubs_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmadds_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
inline void fnmsubs_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b);
// PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions
inline void frsp( FloatRegister d, FloatRegister b);
inline void fctid( FloatRegister d, FloatRegister b);

View File

@ -700,6 +700,26 @@ inline void Assembler::fdiv_( FloatRegister d, FloatRegister a, FloatRegister b)
inline void Assembler::fdivs( FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(0)); }
inline void Assembler::fdivs_(FloatRegister d, FloatRegister a, FloatRegister b) { emit_int32( FDIVS_OPCODE | frt(d) | fra(a) | frb(b) | rc(1)); }
// Fused multiply-accumulate instructions.
// WARNING: Use only when rounding between the 2 parts is not desired.
// Some floating point tck tests will fail if used incorrectly.
inline void Assembler::fmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
inline void Assembler::fmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fmadds_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
inline void Assembler::fmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
inline void Assembler::fmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fmsubs_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
inline void Assembler::fnmadd( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fnmadd_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADD_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
inline void Assembler::fnmadds( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fnmadds_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMADDS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
inline void Assembler::fnmsub( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fnmsub_( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUB_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
inline void Assembler::fnmsubs( FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(0)); }
inline void Assembler::fnmsubs_(FloatRegister d, FloatRegister a, FloatRegister c, FloatRegister b) { emit_int32( FNMSUBS_OPCODE | frt(d) | fra(a) | frb(b) | frc(c) | rc(1)); }
// PPC 1, section 4.6.6 Floating-Point Rounding and Conversion Instructions
inline void Assembler::frsp( FloatRegister d, FloatRegister b) { emit_int32( FRSP_OPCODE | frt(d) | frb(b) | rc(0)); }
inline void Assembler::fctid( FloatRegister d, FloatRegister b) { emit_int32( FCTID_OPCODE | frt(d) | frb(b) | rc(0)); }

View File

@ -292,28 +292,28 @@ void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo *info) {
}
void LIR_Assembler::emit_op3(LIR_Op3* op) {
const bool is_int = op->result_opr()->is_single_cpu();
Register Rdividend = is_int ? op->in_opr1()->as_register() : op->in_opr1()->as_register_lo();
void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) {
const bool is_int = result->is_single_cpu();
Register Rdividend = is_int ? left->as_register() : left->as_register_lo();
Register Rdivisor = noreg;
Register Rscratch = op->in_opr3()->as_register();
Register Rresult = is_int ? op->result_opr()->as_register() : op->result_opr()->as_register_lo();
Register Rscratch = temp->as_register();
Register Rresult = is_int ? result->as_register() : result->as_register_lo();
long divisor = -1;
if (op->in_opr2()->is_register()) {
Rdivisor = is_int ? op->in_opr2()->as_register() : op->in_opr2()->as_register_lo();
if (right->is_register()) {
Rdivisor = is_int ? right->as_register() : right->as_register_lo();
} else {
divisor = is_int ? op->in_opr2()->as_constant_ptr()->as_jint()
: op->in_opr2()->as_constant_ptr()->as_jlong();
divisor = is_int ? right->as_constant_ptr()->as_jint()
: right->as_constant_ptr()->as_jlong();
}
assert(Rdividend != Rscratch, "");
assert(Rdivisor != Rscratch, "");
assert(op->code() == lir_idiv || op->code() == lir_irem, "Must be irem or idiv");
assert(code == lir_idiv || code == lir_irem, "Must be irem or idiv");
if (Rdivisor == noreg) {
if (divisor == 1) { // stupid, but can happen
if (op->code() == lir_idiv) {
if (code == lir_idiv) {
__ mr_if_needed(Rresult, Rdividend);
} else {
__ li(Rresult, 0);
@ -340,7 +340,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
}
__ add(Rscratch, Rdividend, Rscratch);
if (op->code() == lir_idiv) {
if (code == lir_idiv) {
if (is_int) {
__ srawi(Rresult, Rscratch, log2);
} else {
@ -352,7 +352,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
}
} else if (divisor == -1) {
if (op->code() == lir_idiv) {
if (code == lir_idiv) {
__ neg(Rresult, Rdividend);
} else {
__ li(Rresult, 0);
@ -360,7 +360,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
} else {
__ load_const_optimized(Rscratch, divisor);
if (op->code() == lir_idiv) {
if (code == lir_idiv) {
if (is_int) {
__ divw(Rresult, Rdividend, Rscratch); // Can't divide minint/-1.
} else {
@ -389,7 +389,7 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
__ cmpdi(CCR0, Rdivisor, -1);
}
__ bne(CCR0, regular);
if (op->code() == lir_idiv) {
if (code == lir_idiv) {
__ neg(Rresult, Rdividend);
__ b(done);
__ bind(regular);
@ -415,6 +415,26 @@ void LIR_Assembler::emit_op3(LIR_Op3* op) {
}
void LIR_Assembler::emit_op3(LIR_Op3* op) {
switch (op->code()) {
case lir_idiv:
case lir_irem:
arithmetic_idiv(op->code(), op->in_opr1(), op->in_opr2(), op->in_opr3(),
op->result_opr(), op->info());
break;
case lir_fmad:
__ fmadd(op->result_opr()->as_double_reg(), op->in_opr1()->as_double_reg(),
op->in_opr2()->as_double_reg(), op->in_opr3()->as_double_reg());
break;
case lir_fmaf:
__ fmadds(op->result_opr()->as_float_reg(), op->in_opr1()->as_float_reg(),
op->in_opr2()->as_float_reg(), op->in_opr3()->as_float_reg());
break;
default: ShouldNotReachHere(); break;
}
}
void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) {
#ifdef ASSERT
assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label");

View File

@ -1435,7 +1435,26 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) {
}
void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
fatal("FMA intrinsic is not implemented on this platform");
assert(x->number_of_arguments() == 3, "wrong type");
assert(UseFMA, "Needs FMA instructions support.");
LIRItem value(x->argument_at(0), this);
LIRItem value1(x->argument_at(1), this);
LIRItem value2(x->argument_at(2), this);
value.load_item();
value1.load_item();
value2.load_item();
LIR_Opr calc_input = value.result();
LIR_Opr calc_input1 = value1.result();
LIR_Opr calc_input2 = value2.result();
LIR_Opr calc_result = rlock_result(x);
switch (x->id()) {
case vmIntrinsics::_fmaD: __ fmad(calc_input, calc_input1, calc_input2, calc_result); break;
case vmIntrinsics::_fmaF: __ fmaf(calc_input, calc_input1, calc_input2, calc_result); break;
default: ShouldNotReachHere();
}
}
void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) {

View File

@ -9569,6 +9569,117 @@ instruct roundFloat_nop(regF dst) %{
ins_pipe(pipe_class_default);
%}
// Multiply-Accumulate
// src1 * src2 + src3
instruct maddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
match(Set dst (FmaF src3 (Binary src1 src2)));
format %{ "FMADDS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fmadds);
__ fmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// src1 * src2 + src3
instruct maddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
match(Set dst (FmaD src3 (Binary src1 src2)));
format %{ "FMADD $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fmadd);
__ fmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// -src1 * src2 + src3 = -(src1*src2-src3)
instruct mnsubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
match(Set dst (FmaF src3 (Binary (NegF src1) src2)));
match(Set dst (FmaF src3 (Binary src1 (NegF src2))));
format %{ "FNMSUBS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fnmsubs);
__ fnmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// -src1 * src2 + src3 = -(src1*src2-src3)
instruct mnsubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
match(Set dst (FmaD src3 (Binary (NegD src1) src2)));
match(Set dst (FmaD src3 (Binary src1 (NegD src2))));
format %{ "FNMSUB $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fnmsub);
__ fnmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// -src1 * src2 - src3 = -(src1*src2+src3)
instruct mnaddF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
match(Set dst (FmaF (NegF src3) (Binary (NegF src1) src2)));
match(Set dst (FmaF (NegF src3) (Binary src1 (NegF src2))));
format %{ "FNMADDS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fnmadds);
__ fnmadds($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// -src1 * src2 - src3 = -(src1*src2+src3)
instruct mnaddD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
match(Set dst (FmaD (NegD src3) (Binary (NegD src1) src2)));
match(Set dst (FmaD (NegD src3) (Binary src1 (NegD src2))));
format %{ "FNMADD $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fnmadd);
__ fnmadd($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// src1 * src2 - src3
instruct msubF_reg_reg(regF dst, regF src1, regF src2, regF src3) %{
match(Set dst (FmaF (NegF src3) (Binary src1 src2)));
format %{ "FMSUBS $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fmsubs);
__ fmsubs($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
// src1 * src2 - src3
instruct msubD_reg_reg(regD dst, regD src1, regD src2, regD src3) %{
match(Set dst (FmaD (NegD src3) (Binary src1 src2)));
format %{ "FMSUB $dst, $src1, $src2, $src3" %}
size(4);
ins_encode %{
// TODO: PPC port $archOpcode(ppc64Opcode_fmsub);
__ fmsub($dst$$FloatRegister, $src1$$FloatRegister, $src2$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_class_default);
%}
//----------Logical Instructions-----------------------------------------------
// And Instructions

View File

@ -1134,14 +1134,57 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call, Regist
// End of helpers
address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) {
if (!Interpreter::math_entry_available(kind)) {
NOT_PRODUCT(__ should_not_reach_here();)
return NULL;
// Decide what to do: Use same platform specific instructions and runtime calls as compilers.
bool use_instruction = false;
address runtime_entry = NULL;
int num_args = 1;
bool double_precision = true;
// PPC64 specific:
switch (kind) {
case Interpreter::java_lang_math_sqrt: use_instruction = VM_Version::has_fsqrt(); break;
case Interpreter::java_lang_math_abs: use_instruction = true; break;
case Interpreter::java_lang_math_fmaF:
case Interpreter::java_lang_math_fmaD: use_instruction = UseFMA; break;
default: break; // Fall back to runtime call.
}
switch (kind) {
case Interpreter::java_lang_math_sin : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsin); break;
case Interpreter::java_lang_math_cos : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dcos); break;
case Interpreter::java_lang_math_tan : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dtan); break;
case Interpreter::java_lang_math_abs : /* run interpreted */ break;
case Interpreter::java_lang_math_sqrt : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dsqrt); break;
case Interpreter::java_lang_math_log : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog); break;
case Interpreter::java_lang_math_log10: runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dlog10); break;
case Interpreter::java_lang_math_pow : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dpow); num_args = 2; break;
case Interpreter::java_lang_math_exp : runtime_entry = CAST_FROM_FN_PTR(address, SharedRuntime::dexp); break;
case Interpreter::java_lang_math_fmaF : /* run interpreted */ num_args = 3; double_precision = false; break;
case Interpreter::java_lang_math_fmaD : /* run interpreted */ num_args = 3; break;
default: ShouldNotReachHere();
}
// Use normal entry if neither instruction nor runtime call is used.
if (!use_instruction && runtime_entry == NULL) return NULL;
address entry = __ pc();
__ lfd(F1_RET, Interpreter::stackElementSize, R15_esp);
// Load arguments
assert(num_args <= 13, "passed in registers");
if (double_precision) {
int offset = (2 * num_args - 1) * Interpreter::stackElementSize;
for (int i = 0; i < num_args; ++i) {
__ lfd(as_FloatRegister(F1_ARG1->encoding() + i), offset, R15_esp);
offset -= 2 * Interpreter::stackElementSize;
}
} else {
int offset = num_args * Interpreter::stackElementSize;
for (int i = 0; i < num_args; ++i) {
__ lfs(as_FloatRegister(F1_ARG1->encoding() + i), offset, R15_esp);
offset -= Interpreter::stackElementSize;
}
}
// Pop c2i arguments (if any) off when we return.
#ifdef ASSERT
@ -1152,15 +1195,30 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M
#endif // ASSERT
__ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
if (kind == Interpreter::java_lang_math_sqrt) {
__ fsqrt(F1_RET, F1_RET);
} else if (kind == Interpreter::java_lang_math_abs) {
__ fabs(F1_RET, F1_RET);
if (use_instruction) {
switch (kind) {
case Interpreter::java_lang_math_sqrt: __ fsqrt(F1_RET, F1); break;
case Interpreter::java_lang_math_abs: __ fabs(F1_RET, F1); break;
case Interpreter::java_lang_math_fmaF: __ fmadds(F1_RET, F1, F2, F3); break;
case Interpreter::java_lang_math_fmaD: __ fmadd(F1_RET, F1, F2, F3); break;
default: ShouldNotReachHere();
}
} else {
ShouldNotReachHere();
// Comment: Can use tail call if the unextended frame is always C ABI compliant:
//__ load_const_optimized(R12_scratch2, runtime_entry, R0);
//__ call_c_and_return_to_caller(R12_scratch2);
// Push a new C frame and save LR.
__ save_LR_CR(R0);
__ push_frame_reg_args(0, R11_scratch1);
__ call_VM_leaf(runtime_entry);
// Pop the C frame and restore LR.
__ pop_frame();
__ restore_LR_CR(R0);
}
// And we're done.
__ blr();
__ flush();

View File

@ -230,9 +230,8 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
}
if (UseFMA) {
warning("FMA instructions are not available on this CPU");
FLAG_SET_DEFAULT(UseFMA, false);
if (FLAG_IS_DEFAULT(UseFMA)) {
FLAG_SET_DEFAULT(UseFMA, true);
}
if (UseSHA) {

View File

@ -299,10 +299,6 @@ class AbstractInterpreter: AllStatic {
}
static void initialize_method_handle_entries();
// PPC-only: Support abs and sqrt like in compiler.
// For others we can use a normal (native) entry.
static bool math_entry_available(MethodKind kind);
};
//------------------------------------------------------------------------------------------------------------------------