8351155: C1/C2: Remove 32-bit x86 specific FP rounding support

Reviewed-by: vlivanov, kvn
This commit is contained in:
Aleksey Shipilev 2025-03-27 18:10:53 +00:00
parent 1bd0ce1f51
commit b73663a2b4
48 changed files with 34 additions and 547 deletions

View File

@ -32,11 +32,6 @@ enum {
pd_hi_word_offset_in_bytes = BytesPerWord
};
// explicit rounding operations are required to implement the strictFP mode
enum {
pd_strict_fp_requires_explicit_rounding = false
};
// FIXME: There are no callee-saved
// registers

View File

@ -407,7 +407,7 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
arithmetic_op_fpu(x->op(), reg, left.result(), right.result());
set_result(x, round_item(reg));
set_result(x, reg);
}
// for _ladd, _lmul, _lsub, _ldiv, _lrem

View File

@ -115,9 +115,6 @@
// C code as the Java calling convention forces doubles to be aligned.
static const bool misaligned_doubles_ok = true;
// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode.
static const bool strict_fp_requires_explicit_rounding = false;
// Are floats converted to double when stored to stack during
// deoptimization?
static constexpr bool float_in_double() { return false; }

View File

@ -4510,18 +4510,6 @@ instruct unnecessary_membar_volatile() %{
%}
//----------Register Move Instructions-----------------------------------------
// instruct roundDouble_nop(regD dst) %{
// match(Set dst (RoundDouble dst));
// ins_pipe(empty);
// %}
// instruct roundFloat_nop(regF dst) %{
// match(Set dst (RoundFloat dst));
// ins_pipe(empty);
// %}
// Cast Index to Pointer for unsafe natives
instruct castX2P(iRegX src, iRegP dst) %{

View File

@ -31,11 +31,6 @@ enum {
pd_hi_word_offset_in_bytes = BytesPerWord
};
// explicit rounding operations are required to implement the strictFP mode
enum {
pd_strict_fp_requires_explicit_rounding = false
};
#ifdef __SOFTFP__
#define SOFT(n) n
#define VFP(n)

View File

@ -101,9 +101,6 @@
// Java calling convention forces doubles to be aligned.
static const bool misaligned_doubles_ok = false;
// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode.
static const bool strict_fp_requires_explicit_rounding = false;
// Are floats converted to double when stored to stack during deoptimization?
// ARM does not handle callee-save floats.
static constexpr bool float_in_double() {

View File

@ -38,12 +38,6 @@ enum {
};
// Explicit rounding operations are not required to implement the strictFP mode.
enum {
pd_strict_fp_requires_explicit_rounding = false
};
// registers
enum {
pd_nof_cpu_regs_frame_map = 32, // Number of registers used during code emission.

View File

@ -115,9 +115,6 @@
// Java calling convention forces doubles to be aligned.
static const bool misaligned_doubles_ok = true;
// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode.
static const bool strict_fp_requires_explicit_rounding = false;
// Do floats take an entire double register or just half?
//
// A float occupies a ppc64 double register. For the allocator, a

View File

@ -9537,28 +9537,6 @@ instruct sqrtF_reg(regF dst, regF src) %{
ins_pipe(pipe_class_default);
%}
instruct roundDouble_nop(regD dst) %{
match(Set dst (RoundDouble dst));
ins_cost(0);
format %{ " -- \t// RoundDouble not needed - empty" %}
size(0);
// PPC results are already "rounded" (i.e., normal-format IEEE).
ins_encode( /*empty*/ );
ins_pipe(pipe_class_default);
%}
instruct roundFloat_nop(regF dst) %{
match(Set dst (RoundFloat dst));
ins_cost(0);
format %{ " -- \t// RoundFloat not needed - empty" %}
size(0);
// PPC results are already "rounded" (i.e., normal-format IEEE).
ins_encode( /*empty*/ );
ins_pipe(pipe_class_default);
%}
// Multiply-Accumulate
// src1 * src2 + src3

View File

@ -32,11 +32,6 @@ enum {
pd_hi_word_offset_in_bytes = BytesPerWord
};
// explicit rounding operations are required to implement the strictFP mode
enum {
pd_strict_fp_requires_explicit_rounding = false
};
// registers
enum {
pd_nof_cpu_regs_frame_map = Register::number_of_registers, // number of registers used during code emission

View File

@ -355,7 +355,7 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
LIR_Opr reg = rlock(x);
arithmetic_op_fpu(x->op(), reg, left.result(), right.result());
set_result(x, round_item(reg));
set_result(x, reg);
}
// for _ladd, _lmul, _lsub, _ldiv, _lrem

View File

@ -114,9 +114,6 @@
// C code as the Java calling convention forces doubles to be aligned.
static const bool misaligned_doubles_ok = true;
// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode.
static const bool strict_fp_requires_explicit_rounding = false;
// Are floats converted to double when stored to stack during
// deoptimization?
static constexpr bool float_in_double() { return false; }

View File

@ -32,11 +32,6 @@ enum {
pd_hi_word_offset_in_bytes = 0
};
// Explicit rounding operations are not required to implement the strictFP mode.
enum {
pd_strict_fp_requires_explicit_rounding = false
};
// registers
enum {
pd_nof_cpu_regs_frame_map = 16, // Number of registers used during code emission.

View File

@ -108,9 +108,6 @@
// Java calling convention forces doubles to be aligned.
static const bool misaligned_doubles_ok = true;
// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode.
static const bool strict_fp_requires_explicit_rounding = false;
// Do floats take an entire double register or just half?
//
// A float in resides in a zarch double register. When storing it by

View File

@ -5317,23 +5317,6 @@ instruct membar_storestore() %{
//----------Register Move Instructions-----------------------------------------
instruct roundDouble_nop(regD dst) %{
match(Set dst (RoundDouble dst));
ins_cost(0);
// TODO: s390 port size(FIXED_SIZE);
// z/Architecture results are already "rounded" (i.e., normal-format IEEE).
ins_encode();
ins_pipe(pipe_class_dummy);
%}
instruct roundFloat_nop(regF dst) %{
match(Set dst (RoundFloat dst));
ins_cost(0);
// TODO: s390 port size(FIXED_SIZE);
// z/Architecture results are already "rounded" (i.e., normal-format IEEE).
ins_encode();
ins_pipe(pipe_class_dummy);
%}
// Cast Long to Pointer for unsafe natives.
instruct castX2P(iRegP dst, iRegL src) %{

View File

@ -31,12 +31,6 @@ enum {
pd_hi_word_offset_in_bytes = BytesPerWord
};
// explicit rounding operations are required to implement the strictFP mode
enum {
pd_strict_fp_requires_explicit_rounding = LP64_ONLY( false ) NOT_LP64 ( true )
};
// registers
enum {
pd_nof_cpu_regs_frame_map = NOT_LP64(8) LP64_ONLY(16), // number of registers used during code emission

View File

@ -345,7 +345,7 @@ void LIRGenerator::do_NegateOp(NegateOp* x) {
__ negate(value.result(), reg);
set_result(x, round_item(reg));
set_result(x, reg);
}
// for _fadd, _fmul, _fsub, _fdiv, _frem
@ -433,7 +433,7 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
__ move(result_reg, result);
} else {
arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), tmp);
set_result(x, round_item(reg));
set_result(x, reg);
}
#else
if ((UseSSE >= 1 && x->op() == Bytecodes::_frem) || (UseSSE >= 2 && x->op() == Bytecodes::_drem)) {
@ -454,7 +454,7 @@ void LIRGenerator::do_ArithmeticOp_FPU(ArithmeticOp* x) {
} else {
arithmetic_op_fpu(x->op(), reg, left.result(), right.result(), tmp);
}
set_result(x, round_item(reg));
set_result(x, reg);
#endif // _LP64
}

View File

@ -624,16 +624,6 @@ void FpuStackAllocator::handle_op1(LIR_Op1* op1) {
break;
}
case lir_roundfp: {
assert(in->is_fpu_register() && !in->is_xmm_register(), "input must be in register");
assert(res->is_stack(), "result must be on stack");
insert_exchange(in);
new_in = to_fpu_stack_top(in);
pop_if_last_use(op1, in);
break;
}
case lir_abs:
case lir_sqrt:
case lir_neg: {

View File

@ -121,13 +121,6 @@
// Java calling convention forces doubles to be aligned.
static const bool misaligned_doubles_ok = true;
// Advertise here if the CPU requires explicit rounding operations to implement strictfp mode.
#ifdef _LP64
static const bool strict_fp_requires_explicit_rounding = false;
#else
static const bool strict_fp_requires_explicit_rounding = true;
#endif
// Are floats converted to double when stored to stack during deoptimization?
// On x64 it is stored without conversion so we can use normal access.
// On x32 it is stored with conversion only when FPU is used for floats.

View File

@ -4225,9 +4225,7 @@ int MatchRule::is_expensive() const {
strcmp(opType,"FmaD") == 0 ||
strcmp(opType,"FmaF") == 0 ||
strcmp(opType,"FmaHF") == 0 ||
strcmp(opType,"RoundDouble")==0 ||
strcmp(opType,"RoundDoubleMode")==0 ||
strcmp(opType,"RoundFloat")==0 ||
strcmp(opType,"ReverseBytesI")==0 ||
strcmp(opType,"ReverseBytesL")==0 ||
strcmp(opType,"ReverseBytesUS")==0 ||

View File

@ -840,7 +840,6 @@ void Canonicalizer::do_Throw (Throw* x) {}
void Canonicalizer::do_Base (Base* x) {}
void Canonicalizer::do_OsrEntry (OsrEntry* x) {}
void Canonicalizer::do_ExceptionObject(ExceptionObject* x) {}
void Canonicalizer::do_RoundFP (RoundFP* x) {}
void Canonicalizer::do_UnsafeGet (UnsafeGet* x) {}
void Canonicalizer::do_UnsafePut (UnsafePut* x) {}
void Canonicalizer::do_UnsafeGetAndSet(UnsafeGetAndSet* x) {}

View File

@ -88,7 +88,6 @@ class Canonicalizer: InstructionVisitor {
virtual void do_Base (Base* x);
virtual void do_OsrEntry (OsrEntry* x);
virtual void do_ExceptionObject(ExceptionObject* x);
virtual void do_RoundFP (RoundFP* x);
virtual void do_UnsafeGet (UnsafeGet* x);
virtual void do_UnsafePut (UnsafePut* x);
virtual void do_UnsafeGetAndSet(UnsafeGetAndSet* x);

View File

@ -44,13 +44,6 @@ enum {
hi_word_offset_in_bytes = pd_hi_word_offset_in_bytes
};
// the processor may require explicit rounding operations to implement the strictFP mode
enum {
strict_fp_requires_explicit_rounding = pd_strict_fp_requires_explicit_rounding
};
// for debug info: a float value in a register may be saved in double precision by runtime stubs
enum {
float_saved_as_double = pd_float_saved_as_double

View File

@ -673,17 +673,6 @@ class MemoryBuffer: public CompilationResourceObj {
return load;
}
if (strict_fp_requires_explicit_rounding && load->type()->is_float_kind()) {
#ifdef IA32
if (UseSSE < 2) {
// can't skip load since value might get rounded as a side effect
return load;
}
#else
Unimplemented();
#endif // IA32
}
ciField* field = load->field();
Value object = load->obj();
if (field->holder()->is_loaded() && !field->is_volatile()) {
@ -1052,7 +1041,7 @@ void GraphBuilder::store_local(ValueStack* state, Value x, int index) {
}
}
state->store_local(index, round_fp(x));
state->store_local(index, x);
}
@ -1204,10 +1193,7 @@ void GraphBuilder::arithmetic_op(ValueType* type, Bytecodes::Code code, ValueSta
Value y = pop(type);
Value x = pop(type);
Value res = new ArithmeticOp(code, x, y, state_before);
// Note: currently single-precision floating-point rounding on Intel is handled at the LIRGenerator level
res = append(res);
res = round_fp(res);
push(type, res);
push(type, append(res));
}
@ -2228,7 +2214,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
append_split(result);
if (result_type != voidType) {
push(result_type, round_fp(result));
push(result_type, result);
}
if (profile_return() && result_type->is_object_kind()) {
profile_return_type(result, target);
@ -2356,29 +2342,6 @@ void GraphBuilder::throw_op(int bci) {
}
Value GraphBuilder::round_fp(Value fp_value) {
if (strict_fp_requires_explicit_rounding) {
#ifdef IA32
// no rounding needed if SSE2 is used
if (UseSSE < 2) {
// Must currently insert rounding node for doubleword values that
// are results of expressions (i.e., not loads from memory or
// constants)
if (fp_value->type()->tag() == doubleTag &&
fp_value->as_Constant() == nullptr &&
fp_value->as_Local() == nullptr && // method parameters need no rounding
fp_value->as_RoundFP() == nullptr) {
return append(new RoundFP(fp_value));
}
}
#else
Unimplemented();
#endif // IA32
}
return fp_value;
}
Instruction* GraphBuilder::append_with_bci(Instruction* instr, int bci) {
Canonicalizer canon(compilation(), instr, bci);
Instruction* i1 = canon.canonical();

View File

@ -266,7 +266,6 @@ class GraphBuilder {
void monitorexit(Value x, int bci);
void new_multi_array(int dimensions);
void throw_op(int bci);
Value round_fp(Value fp_value);
// stack/code manipulation helpers
Instruction* append_with_bci(Instruction* instr, int bci);

View File

@ -91,7 +91,6 @@ class LookupSwitch;
class Return;
class Throw;
class Base;
class RoundFP;
class UnsafeOp;
class UnsafeGet;
class UnsafePut;
@ -187,7 +186,6 @@ class InstructionVisitor: public StackObj {
virtual void do_Base (Base* x) = 0;
virtual void do_OsrEntry (OsrEntry* x) = 0;
virtual void do_ExceptionObject(ExceptionObject* x) = 0;
virtual void do_RoundFP (RoundFP* x) = 0;
virtual void do_UnsafeGet (UnsafeGet* x) = 0;
virtual void do_UnsafePut (UnsafePut* x) = 0;
virtual void do_UnsafeGetAndSet(UnsafeGetAndSet* x) = 0;
@ -556,7 +554,6 @@ class Instruction: public CompilationResourceObj {
virtual Return* as_Return() { return nullptr; }
virtual Throw* as_Throw() { return nullptr; }
virtual Base* as_Base() { return nullptr; }
virtual RoundFP* as_RoundFP() { return nullptr; }
virtual ExceptionObject* as_ExceptionObject() { return nullptr; }
virtual UnsafeOp* as_UnsafeOp() { return nullptr; }
virtual ProfileInvoke* as_ProfileInvoke() { return nullptr; }
@ -2142,30 +2139,6 @@ LEAF(ExceptionObject, Instruction)
};
// Models needed rounding for floating-point values on Intel.
// Currently only used to represent rounding of double-precision
// values stored into local variables, but could be used to model
// intermediate rounding of single-precision values as well.
LEAF(RoundFP, Instruction)
private:
Value _input; // floating-point value to be rounded
public:
RoundFP(Value input)
: Instruction(input->type()) // Note: should not be used for constants
, _input(input)
{
ASSERT_VALUES
}
// accessors
Value input() const { return _input; }
// generic
virtual void input_values_do(ValueVisitor* f) { f->visit(&_input); }
};
BASE(UnsafeOp, Instruction)
private:
Value _object; // Object to be fetched from or mutated

View File

@ -779,12 +779,6 @@ void InstructionPrinter::do_ExceptionObject(ExceptionObject* x) {
output()->print("incoming exception");
}
void InstructionPrinter::do_RoundFP(RoundFP* x) {
output()->print("round_fp ");
print_value(x->input());
}
void InstructionPrinter::do_UnsafeGet(UnsafeGet* x) {
print_unsafe_op(x, x->is_raw() ? "UnsafeGet (raw)" : "UnsafeGet");
output()->put(')');

View File

@ -120,7 +120,6 @@ class InstructionPrinter: public InstructionVisitor {
virtual void do_Base (Base* x);
virtual void do_OsrEntry (OsrEntry* x);
virtual void do_ExceptionObject(ExceptionObject* x);
virtual void do_RoundFP (RoundFP* x);
virtual void do_UnsafeGet (UnsafeGet* x);
virtual void do_UnsafePut (UnsafePut* x);
virtual void do_UnsafeGetAndSet(UnsafeGetAndSet* x);

View File

@ -550,20 +550,6 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
}
// LIR_OpRoundFP;
case lir_roundfp: {
assert(op->as_OpRoundFP() != nullptr, "must be");
LIR_OpRoundFP* opRoundFP = (LIR_OpRoundFP*)op;
assert(op->_info == nullptr, "info not used by this instruction");
assert(opRoundFP->_tmp->is_illegal(), "not used");
do_input(opRoundFP->_opr);
do_output(opRoundFP->_result);
break;
}
// LIR_Op2
case lir_cmp:
case lir_cmp_l2i:
@ -1731,7 +1717,6 @@ const char * LIR_Op::name() const {
case lir_branch: s = "branch"; break;
case lir_cond_float_branch: s = "flt_cond_br"; break;
case lir_move: s = "move"; break;
case lir_roundfp: s = "roundfp"; break;
case lir_abs: s = "abs"; break;
case lir_neg: s = "neg"; break;
case lir_sqrt: s = "sqrt"; break;
@ -1976,12 +1961,6 @@ void LIR_OpAllocObj::print_instr(outputStream* out) const {
out->print("[lbl:" INTPTR_FORMAT "]", p2i(stub()->entry()));
}
void LIR_OpRoundFP::print_instr(outputStream* out) const {
_opr->print(out); out->print(" ");
tmp()->print(out); out->print(" ");
result_opr()->print(out); out->print(" ");
}
// LIR_Op2
void LIR_Op2::print_instr(outputStream* out) const {
if (code() == lir_cmp || code() == lir_branch || code() == lir_cond_float_branch) {

View File

@ -884,7 +884,6 @@ class LIR_OpBranch;
class LIR_OpConvert;
class LIR_OpAllocObj;
class LIR_OpReturn;
class LIR_OpRoundFP;
class LIR_Op2;
class LIR_OpDelay;
class LIR_Op3;
@ -938,7 +937,6 @@ enum LIR_Code {
, lir_convert
, lir_alloc_object
, lir_monaddr
, lir_roundfp
, lir_sqrt
, lir_abs
, lir_neg
@ -1147,7 +1145,6 @@ class LIR_Op: public CompilationResourceObj {
virtual LIR_OpLock* as_OpLock() { return nullptr; }
virtual LIR_OpAllocArray* as_OpAllocArray() { return nullptr; }
virtual LIR_OpAllocObj* as_OpAllocObj() { return nullptr; }
virtual LIR_OpRoundFP* as_OpRoundFP() { return nullptr; }
virtual LIR_OpBranch* as_OpBranch() { return nullptr; }
virtual LIR_OpReturn* as_OpReturn() { return nullptr; }
virtual LIR_OpRTCall* as_OpRTCall() { return nullptr; }
@ -1527,23 +1524,6 @@ class LIR_OpAllocObj : public LIR_Op1 {
};
// LIR_OpRoundFP
class LIR_OpRoundFP : public LIR_Op1 {
friend class LIR_OpVisitState;
private:
LIR_Opr _tmp;
public:
LIR_OpRoundFP(LIR_Opr reg, LIR_Opr stack_loc_temp, LIR_Opr result)
: LIR_Op1(lir_roundfp, reg, result)
, _tmp(stack_loc_temp) {}
LIR_Opr tmp() const { return _tmp; }
virtual LIR_OpRoundFP* as_OpRoundFP() { return this; }
void print_instr(outputStream* out) const PRODUCT_RETURN;
};
// LIR_OpTypeCheck
class LIR_OpTypeCheck: public LIR_Op {
friend class LIR_OpVisitState;
@ -2205,7 +2185,6 @@ class LIR_List: public CompilationResourceObj {
// result is a stack location for old backend and vreg for UseLinearScan
// stack_loc_temp is an illegal register for old backend
void roundfp(LIR_Opr reg, LIR_Opr stack_loc_temp, LIR_Opr result) { append(new LIR_OpRoundFP(reg, stack_loc_temp, result)); }
void move(LIR_Opr src, LIR_Opr dst, CodeEmitInfo* info = nullptr) { append(new LIR_Op1(lir_move, src, dst, dst->type(), lir_patch_none, info)); }
void move(LIR_Address* src, LIR_Opr dst, CodeEmitInfo* info = nullptr) { append(new LIR_Op1(lir_move, LIR_OprFact::address(src), dst, src->type(), lir_patch_none, info)); }
void move(LIR_Opr src, LIR_Address* dst, CodeEmitInfo* info = nullptr) { append(new LIR_Op1(lir_move, src, LIR_OprFact::address(dst), dst->type(), lir_patch_none, info)); }

View File

@ -519,12 +519,6 @@ void LIR_Assembler::emit_op1(LIR_Op1* op) {
}
break;
case lir_roundfp: {
LIR_OpRoundFP* round_op = op->as_OpRoundFP();
roundfp_op(round_op->in_opr(), round_op->tmp(), round_op->result_opr(), round_op->pop_fpu_stack());
break;
}
case lir_abs:
case lir_sqrt:
case lir_f2hf:
@ -775,16 +769,6 @@ void LIR_Assembler::build_frame() {
}
void LIR_Assembler::roundfp_op(LIR_Opr src, LIR_Opr tmp, LIR_Opr dest, bool pop_fpu_stack) {
assert(strict_fp_requires_explicit_rounding, "not required");
assert((src->is_single_fpu() && dest->is_single_stack()) ||
(src->is_double_fpu() && dest->is_double_stack()),
"round_fp: rounds register -> stack location");
reg2stack (src, dest, src->type(), pop_fpu_stack);
}
void LIR_Assembler::move_op(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide) {
if (src->is_register()) {
if (dest->is_register()) {

View File

@ -215,7 +215,6 @@ class LIR_Assembler: public CompilationResourceObj {
void logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest);
void roundfp_op(LIR_Opr src, LIR_Opr tmp, LIR_Opr dest, bool pop_fpu_stack);
void move_op(LIR_Opr src, LIR_Opr result, BasicType type,
LIR_PatchCode patch_code, CodeEmitInfo* info, bool pop_fpu_stack, bool wide);
void volatile_move_op(LIR_Opr src, LIR_Opr result, BasicType type, CodeEmitInfo* info);

View File

@ -881,27 +881,6 @@ void LIRGenerator::arraycopy_helper(Intrinsic* x, int* flagsp, ciArrayKlass** ex
}
LIR_Opr LIRGenerator::round_item(LIR_Opr opr) {
assert(opr->is_register(), "why spill if item is not register?");
if (strict_fp_requires_explicit_rounding) {
#ifdef IA32
if (UseSSE < 1 && opr->is_single_fpu()) {
LIR_Opr result = new_register(T_FLOAT);
set_vreg_flag(result, must_start_in_memory);
assert(opr->is_register(), "only a register can be spilled");
assert(opr->value_type()->is_float(), "rounding only for floats available");
__ roundfp(opr, LIR_OprFact::illegalOpr, result);
return result;
}
#else
Unimplemented();
#endif // IA32
}
return opr;
}
LIR_Opr LIRGenerator::force_to_spill(LIR_Opr value, BasicType t) {
assert(type2size[t] == type2size[value->type()],
"size mismatch: t=%s, value->type()=%s", type2name(t), type2name(value->type()));
@ -2053,25 +2032,6 @@ void LIRGenerator::do_Throw(Throw* x) {
}
void LIRGenerator::do_RoundFP(RoundFP* x) {
assert(strict_fp_requires_explicit_rounding, "not required");
LIRItem input(x->input(), this);
input.load_item();
LIR_Opr input_opr = input.result();
assert(input_opr->is_register(), "why round if value is not in a register?");
assert(input_opr->is_single_fpu() || input_opr->is_double_fpu(), "input should be floating-point value");
if (input_opr->is_single_fpu()) {
set_result(x, round_item(input_opr)); // This code path not currently taken
} else {
LIR_Opr result = new_register(T_DOUBLE);
set_vreg_flag(result, must_start_in_memory);
__ roundfp(input_opr, LIR_OprFact::illegalOpr, result);
set_result(x, result);
}
}
void LIRGenerator::do_UnsafeGet(UnsafeGet* x) {
BasicType type = x->basic_type();
LIRItem src(x->object(), this);

View File

@ -233,7 +233,6 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
friend class LIRItem;
LIR_Opr round_item(LIR_Opr opr);
LIR_Opr force_to_spill(LIR_Opr value, BasicType t);
PhiResolverState& resolver_state() { return _resolver_state; }
@ -579,7 +578,6 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
virtual void do_Base (Base* x);
virtual void do_OsrEntry (OsrEntry* x);
virtual void do_ExceptionObject(ExceptionObject* x);
virtual void do_RoundFP (RoundFP* x);
virtual void do_UnsafeGet (UnsafeGet* x);
virtual void do_UnsafePut (UnsafePut* x);
virtual void do_UnsafeGetAndSet(UnsafeGetAndSet* x);

View File

@ -5888,7 +5888,6 @@ bool LinearScanWalker::activate_current() {
} else if (allocator()->gen()->is_vreg_flag_set(cur->reg_num(), LIRGenerator::must_start_in_memory)) {
// activating an interval that must start in a stack slot, but may get a register later
// used for lir_roundfp: rounding is done by store to stack and reload later
TRACE_LINEAR_SCAN(4, tty->print_cr(" interval must start in stack slot -> split it before first use"));
assert(cur->assigned_reg() == any_reg && cur->assigned_regHi() == any_reg, "register already assigned");
@ -6770,7 +6769,6 @@ void LinearScanStatistic::collect(LinearScan* allocator) {
case lir_push:
case lir_pop:
case lir_convert:
case lir_roundfp:
case lir_cmove: inc_counter(counter_misc_inst); break;
default: inc_counter(counter_other_inst); break;

View File

@ -577,7 +577,6 @@ public:
void do_Base (Base* x);
void do_OsrEntry (OsrEntry* x);
void do_ExceptionObject(ExceptionObject* x);
void do_RoundFP (RoundFP* x);
void do_UnsafeGet (UnsafeGet* x);
void do_UnsafePut (UnsafePut* x);
void do_UnsafeGetAndSet(UnsafeGetAndSet* x);
@ -762,7 +761,6 @@ void NullCheckVisitor::do_Throw (Throw* x) { nce()->clear_las
void NullCheckVisitor::do_Base (Base* x) {}
void NullCheckVisitor::do_OsrEntry (OsrEntry* x) {}
void NullCheckVisitor::do_ExceptionObject(ExceptionObject* x) { nce()->handle_ExceptionObject(x); }
void NullCheckVisitor::do_RoundFP (RoundFP* x) {}
void NullCheckVisitor::do_UnsafeGet (UnsafeGet* x) {}
void NullCheckVisitor::do_UnsafePut (UnsafePut* x) {}
void NullCheckVisitor::do_UnsafeGetAndSet(UnsafeGetAndSet* x) {}

View File

@ -154,7 +154,6 @@ public:
void do_Base (Base* x) { /* nothing to do */ };
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ };
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ };
void do_RoundFP (RoundFP* x) { /* nothing to do */ };
void do_UnsafePut (UnsafePut* x) { /* nothing to do */ };
void do_UnsafeGet (UnsafeGet* x) { /* nothing to do */ };
void do_UnsafeGetAndSet(UnsafeGetAndSet* x) { /* nothing to do */ };

View File

@ -203,7 +203,6 @@ class ValueNumberingVisitor: public InstructionVisitor {
void do_Base (Base* x) { /* nothing to do */ }
void do_OsrEntry (OsrEntry* x) { /* nothing to do */ }
void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
void do_RoundFP (RoundFP* x) { /* nothing to do */ }
void do_ProfileCall (ProfileCall* x) { /* nothing to do */ }
void do_ProfileReturnType (ProfileReturnType* x) { /* nothing to do */ }
void do_ProfileInvoke (ProfileInvoke* x) { /* nothing to do */ };

View File

@ -149,11 +149,6 @@ Node* BarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) cons
C2ParseAccess& parse_access = static_cast<C2ParseAccess&>(access);
GraphKit* kit = parse_access.kit();
if (bt == T_DOUBLE) {
Node* new_val = kit->dprecision_rounding(val.node());
val.set_node(new_val);
}
store = kit->store_to_memory(kit->control(), access.addr().node(), val.node(), bt,
mo, requires_atomic_access, unaligned, mismatched,
unsafe, access.barrier_data());

View File

@ -313,10 +313,8 @@ macro(ReverseI)
macro(ReverseL)
macro(ReverseV)
macro(Root)
macro(RoundDouble)
macro(RoundDoubleMode)
macro(RoundDoubleModeV)
macro(RoundFloat)
macro(RotateLeft)
macro(RotateLeftV)
macro(RotateRight)

View File

@ -181,16 +181,6 @@ const Type* ConvD2INode::Value(PhaseGVN* phase) const {
return TypeInt::make( SharedRuntime::d2i( td->getd() ) );
}
//------------------------------Ideal------------------------------------------
// If converting to an int type, skip any rounding nodes
Node *ConvD2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (in(1)->Opcode() == Op_RoundDouble) {
set_req(1, in(1)->in(1));
return this;
}
return nullptr;
}
//------------------------------Identity---------------------------------------
// Int's can be converted to doubles with no loss of bits. Hence
// converting an integer to a double and back to an integer is a NOP.
@ -217,16 +207,6 @@ Node* ConvD2LNode::Identity(PhaseGVN* phase) {
return this;
}
//------------------------------Ideal------------------------------------------
// If converting to an int type, skip any rounding nodes
Node *ConvD2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (in(1)->Opcode() == Op_RoundDouble) {
set_req(1, in(1)->in(1));
return this;
}
return nullptr;
}
//=============================================================================
//------------------------------Value------------------------------------------
const Type* ConvF2DNode::Value(PhaseGVN* phase) const {
@ -300,16 +280,6 @@ Node* ConvF2INode::Identity(PhaseGVN* phase) {
return this;
}
//------------------------------Ideal------------------------------------------
// If converting to an int type, skip any rounding nodes
Node *ConvF2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (in(1)->Opcode() == Op_RoundFloat) {
set_req(1, in(1)->in(1));
return this;
}
return nullptr;
}
//=============================================================================
//------------------------------Value------------------------------------------
const Type* ConvF2LNode::Value(PhaseGVN* phase) const {
@ -329,16 +299,6 @@ Node* ConvF2LNode::Identity(PhaseGVN* phase) {
return this;
}
//------------------------------Ideal------------------------------------------
// If converting to an int type, skip any rounding nodes
Node *ConvF2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (in(1)->Opcode() == Op_RoundFloat) {
set_req(1, in(1)->in(1));
return this;
}
return nullptr;
}
//=============================================================================
//------------------------------Value------------------------------------------
const Type* ConvHF2FNode::Value(PhaseGVN* phase) const {
@ -865,52 +825,6 @@ Node *ConvL2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
return nullptr;
}
//=============================================================================
//------------------------------Identity---------------------------------------
// Remove redundant roundings
Node* RoundFloatNode::Identity(PhaseGVN* phase) {
assert(Matcher::strict_fp_requires_explicit_rounding, "should only generate for Intel");
// Do not round constants
if (phase->type(in(1))->base() == Type::FloatCon) return in(1);
int op = in(1)->Opcode();
// Redundant rounding
if( op == Op_RoundFloat ) return in(1);
// Already rounded
if( op == Op_Parm ) return in(1);
if( op == Op_LoadF ) return in(1);
return this;
}
//------------------------------Value------------------------------------------
const Type* RoundFloatNode::Value(PhaseGVN* phase) const {
return phase->type( in(1) );
}
//=============================================================================
//------------------------------Identity---------------------------------------
// Remove redundant roundings. Incoming arguments are already rounded.
Node* RoundDoubleNode::Identity(PhaseGVN* phase) {
assert(Matcher::strict_fp_requires_explicit_rounding, "should only generate for Intel");
// Do not round constants
if (phase->type(in(1))->base() == Type::DoubleCon) return in(1);
int op = in(1)->Opcode();
// Redundant rounding
if( op == Op_RoundDouble ) return in(1);
// Already rounded
if( op == Op_Parm ) return in(1);
if( op == Op_LoadD ) return in(1);
if( op == Op_ConvF2D ) return in(1);
if( op == Op_ConvI2D ) return in(1);
return this;
}
//------------------------------Value------------------------------------------
const Type* RoundDoubleNode::Value(PhaseGVN* phase) const {
return phase->type( in(1) );
}
//=============================================================================
RoundDoubleModeNode* RoundDoubleModeNode::make(PhaseGVN& gvn, Node* arg, RoundDoubleModeNode::RoundingMode rmode) {
ConINode* rm = gvn.intcon(rmode);

View File

@ -79,7 +79,6 @@ class ConvD2INode : public ConvertNode {
virtual const Type* in_type() const { return Type::DOUBLE; }
virtual const Type* Value(PhaseGVN* phase) const;
virtual Node* Identity(PhaseGVN* phase);
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
};
//------------------------------ConvD2LNode------------------------------------
@ -91,7 +90,6 @@ class ConvD2LNode : public ConvertNode {
virtual const Type* in_type() const { return Type::DOUBLE; }
virtual const Type* Value(PhaseGVN* phase) const;
virtual Node* Identity(PhaseGVN* phase);
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
};
//------------------------------ConvF2DNode------------------------------------
@ -124,7 +122,6 @@ public:
virtual const Type* in_type() const { return TypeInt::FLOAT; }
virtual const Type* Value(PhaseGVN* phase) const;
virtual Node* Identity(PhaseGVN* phase);
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
};
//------------------------------ConvF2LNode------------------------------------
@ -136,7 +133,6 @@ public:
virtual const Type* in_type() const { return TypeInt::FLOAT; }
virtual const Type* Value(PhaseGVN* phase) const;
virtual Node* Identity(PhaseGVN* phase);
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
};
//------------------------------ConvHF2FNode------------------------------------
@ -254,28 +250,6 @@ public:
virtual uint ideal_reg() const { return Op_RegI; }
};
//-----------------------------RoundFloatNode----------------------------------
class RoundFloatNode: public Node {
public:
RoundFloatNode(Node* c, Node *in1): Node(c, in1) {}
virtual int Opcode() const;
virtual const Type *bottom_type() const { return Type::FLOAT; }
virtual uint ideal_reg() const { return Op_RegF; }
virtual Node* Identity(PhaseGVN* phase);
virtual const Type* Value(PhaseGVN* phase) const;
};
//-----------------------------RoundDoubleNode---------------------------------
class RoundDoubleNode: public Node {
public:
RoundDoubleNode(Node* c, Node *in1): Node(c, in1) {}
virtual int Opcode() const;
virtual const Type *bottom_type() const { return Type::DOUBLE; }
virtual uint ideal_reg() const { return Op_RegD; }
virtual Node* Identity(PhaseGVN* phase);
virtual const Type* Value(PhaseGVN* phase) const;
};
//-----------------------------RoundDoubleModeNode-----------------------------
class RoundDoubleModeNode: public Node {

View File

@ -648,8 +648,6 @@ void Parse::do_call() {
orig_callee = callee = nullptr;
// ---------------------
// Round double arguments before call
round_double_arguments(cg->method());
// Feed profiling data for arguments to the type system so it can
// propagate it as speculative types

View File

@ -2364,51 +2364,6 @@ void GraphKit::record_profiled_return_for_speculation() {
}
}
void GraphKit::round_double_arguments(ciMethod* dest_method) {
if (Matcher::strict_fp_requires_explicit_rounding) {
// (Note: TypeFunc::make has a cache that makes this fast.)
const TypeFunc* tf = TypeFunc::make(dest_method);
int nargs = tf->domain()->cnt() - TypeFunc::Parms;
for (int j = 0; j < nargs; j++) {
const Type *targ = tf->domain()->field_at(j + TypeFunc::Parms);
if (targ->basic_type() == T_DOUBLE) {
// If any parameters are doubles, they must be rounded before
// the call, dprecision_rounding does gvn.transform
Node *arg = argument(j);
arg = dprecision_rounding(arg);
set_argument(j, arg);
}
}
}
}
// rounding for strict float precision conformance
Node* GraphKit::precision_rounding(Node* n) {
if (Matcher::strict_fp_requires_explicit_rounding) {
#ifdef IA32
if (UseSSE == 0) {
return _gvn.transform(new RoundFloatNode(nullptr, n));
}
#else
Unimplemented();
#endif // IA32
}
return n;
}
// rounding for strict double precision conformance
Node* GraphKit::dprecision_rounding(Node *n) {
if (Matcher::strict_fp_requires_explicit_rounding) {
#ifdef IA32
if (UseSSE < 2) {
return _gvn.transform(new RoundDoubleNode(nullptr, n));
}
#else
Unimplemented();
#endif // IA32
}
return n;
}
//=============================================================================
// Generate a fast path/slow path idiom. Graph looks like:

View File

@ -752,15 +752,6 @@ class GraphKit : public Phase {
void final_sync(IdealKit& ideal);
public:
// Helper function to round double arguments before a call
void round_double_arguments(ciMethod* dest_method);
// rounding for strict float precision conformance
Node* precision_rounding(Node* n);
// rounding for strict double precision conformance
Node* dprecision_rounding(Node* n);
// Helper functions for fast/slow path codes
Node* opt_iff(Node* region, Node* iff);
Node* make_runtime_call(int flags,

View File

@ -1721,20 +1721,6 @@ bool LibraryCallKit::inline_string_char_access(bool is_store) {
return true;
}
//--------------------------round_double_node--------------------------------
// Round a double node if necessary.
Node* LibraryCallKit::round_double_node(Node* n) {
if (Matcher::strict_fp_requires_explicit_rounding) {
#ifdef IA32
if (UseSSE < 2) {
n = _gvn.transform(new RoundDoubleNode(nullptr, n));
}
#else
Unimplemented();
#endif // IA32
}
return n;
}
//------------------------------inline_math-----------------------------------
// public static double Math.abs(double)
@ -1743,7 +1729,7 @@ Node* LibraryCallKit::round_double_node(Node* n) {
// public static double Math.log10(double)
// public static double Math.round(double)
bool LibraryCallKit::inline_double_math(vmIntrinsics::ID id) {
Node* arg = round_double_node(argument(0));
Node* arg = argument(0);
Node* n = nullptr;
switch (id) {
case vmIntrinsics::_dabs: n = new AbsDNode( arg); break;
@ -1754,7 +1740,7 @@ bool LibraryCallKit::inline_double_math(vmIntrinsics::ID id) {
case vmIntrinsics::_floor: n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_floor); break;
case vmIntrinsics::_rint: n = RoundDoubleModeNode::make(_gvn, arg, RoundDoubleModeNode::rmode_rint); break;
case vmIntrinsics::_roundD: n = new RoundDNode(arg); break;
case vmIntrinsics::_dcopySign: n = CopySignDNode::make(_gvn, arg, round_double_node(argument(2))); break;
case vmIntrinsics::_dcopySign: n = CopySignDNode::make(_gvn, arg, argument(2)); break;
case vmIntrinsics::_dsignum: n = SignumDNode::make(_gvn, arg); break;
default: fatal_unexpected_iid(id); break;
}
@ -1788,8 +1774,8 @@ bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, c
"must be (DD)D or (D)D type");
// Inputs
Node* a = round_double_node(argument(0));
Node* b = (call_type == OptoRuntime::Math_DD_D_Type()) ? round_double_node(argument(2)) : nullptr;
Node* a = argument(0);
Node* b = (call_type == OptoRuntime::Math_DD_D_Type()) ? argument(2) : nullptr;
const TypePtr* no_memory_effects = nullptr;
Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
@ -1807,17 +1793,17 @@ bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, c
//------------------------------inline_math_pow-----------------------------
bool LibraryCallKit::inline_math_pow() {
Node* exp = round_double_node(argument(2));
Node* exp = argument(2);
const TypeD* d = _gvn.type(exp)->isa_double_constant();
if (d != nullptr) {
if (d->getd() == 2.0) {
// Special case: pow(x, 2.0) => x * x
Node* base = round_double_node(argument(0));
Node* base = argument(0);
set_result(_gvn.transform(new MulDNode(base, base)));
return true;
} else if (d->getd() == 0.5 && Matcher::match_rule_supported(Op_SqrtD)) {
// Special case: pow(x, 0.5) => sqrt(x)
Node* base = round_double_node(argument(0));
Node* base = argument(0);
Node* zero = _gvn.zerocon(T_DOUBLE);
RegionNode* region = new RegionNode(3);
@ -1963,8 +1949,8 @@ bool LibraryCallKit::inline_min_max(vmIntrinsics::ID id) {
case vmIntrinsics::_minD_strict:
case vmIntrinsics::_maxD_strict:
assert(callee()->signature()->size() == 4, "minD/maxD has 2 parameters of size 2 each.");
a = round_double_node(argument(0));
b = round_double_node(argument(2));
a = argument(0);
b = argument(2);
break;
case vmIntrinsics::_minL:
case vmIntrinsics::_maxL:
@ -8483,9 +8469,9 @@ bool LibraryCallKit::inline_fma(vmIntrinsics::ID id) {
case vmIntrinsics::_fmaD:
assert(callee()->signature()->size() == 6, "fma has 3 parameters of size 2 each.");
// no receiver since it is static method
a = round_double_node(argument(0));
b = round_double_node(argument(2));
c = round_double_node(argument(4));
a = argument(0);
b = argument(2);
c = argument(4);
result = _gvn.transform(new FmaDNode(a, b, c));
break;
case vmIntrinsics::_fmaF:

View File

@ -202,7 +202,6 @@ class LibraryCallKit : public GraphKit {
bool inline_string_getCharsU();
bool inline_string_copy(bool compress);
bool inline_string_char_access(bool is_store);
Node* round_double_node(Node* n);
bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
bool inline_math_native(vmIntrinsics::ID id);
bool inline_math(vmIntrinsics::ID id);

View File

@ -2062,19 +2062,19 @@ void Parse::do_one_bytecode() {
// double stores
case Bytecodes::_dstore_0:
set_pair_local( 0, dprecision_rounding(pop_pair()) );
set_pair_local( 0, pop_pair() );
break;
case Bytecodes::_dstore_1:
set_pair_local( 1, dprecision_rounding(pop_pair()) );
set_pair_local( 1, pop_pair() );
break;
case Bytecodes::_dstore_2:
set_pair_local( 2, dprecision_rounding(pop_pair()) );
set_pair_local( 2, pop_pair() );
break;
case Bytecodes::_dstore_3:
set_pair_local( 3, dprecision_rounding(pop_pair()) );
set_pair_local( 3, pop_pair() );
break;
case Bytecodes::_dstore:
set_pair_local( iter().get_index(), dprecision_rounding(pop_pair()) );
set_pair_local( iter().get_index(), pop_pair() );
break;
case Bytecodes::_pop: dec_sp(1); break;
@ -2256,32 +2256,28 @@ void Parse::do_one_bytecode() {
b = pop();
a = pop();
c = _gvn.transform( new SubFNode(a,b) );
d = precision_rounding(c);
push( d );
push(c);
break;
case Bytecodes::_fadd:
b = pop();
a = pop();
c = _gvn.transform( new AddFNode(a,b) );
d = precision_rounding(c);
push( d );
push(c);
break;
case Bytecodes::_fmul:
b = pop();
a = pop();
c = _gvn.transform( new MulFNode(a,b) );
d = precision_rounding(c);
push( d );
push(c);
break;
case Bytecodes::_fdiv:
b = pop();
a = pop();
c = _gvn.transform( new DivFNode(nullptr,a,b) );
d = precision_rounding(c);
push( d );
push(c);
break;
case Bytecodes::_frem:
@ -2331,8 +2327,6 @@ void Parse::do_one_bytecode() {
case Bytecodes::_d2f:
a = pop_pair();
b = _gvn.transform( new ConvD2FNode(a));
// This breaks _227_mtrt (speed & correctness) and _222_mpegaudio (speed)
//b = _gvn.transform(new RoundFloatNode(nullptr, b) );
push( b );
break;
@ -2340,11 +2334,6 @@ void Parse::do_one_bytecode() {
if (Matcher::convL2FSupported()) {
a = pop_pair();
b = _gvn.transform( new ConvL2FNode(a));
// For x86_32.ad, FILD doesn't restrict precision to 24 or 53 bits.
// Rather than storing the result into an FP register then pushing
// out to memory to round, the machine instruction that implements
// ConvL2D is responsible for rounding.
// c = precision_rounding(b);
push(b);
} else {
l2f();
@ -2354,8 +2343,6 @@ void Parse::do_one_bytecode() {
case Bytecodes::_l2d:
a = pop_pair();
b = _gvn.transform( new ConvL2DNode(a));
// For x86_32.ad, rounding is always necessary (see _l2f above).
// c = dprecision_rounding(b);
push_pair(b);
break;
@ -2375,32 +2362,28 @@ void Parse::do_one_bytecode() {
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new SubDNode(a,b) );
d = dprecision_rounding(c);
push_pair( d );
push_pair(c);
break;
case Bytecodes::_dadd:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new AddDNode(a,b) );
d = dprecision_rounding(c);
push_pair( d );
push_pair(c);
break;
case Bytecodes::_dmul:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new MulDNode(a,b) );
d = dprecision_rounding(c);
push_pair( d );
push_pair(c);
break;
case Bytecodes::_ddiv:
b = pop_pair();
a = pop_pair();
c = _gvn.transform( new DivDNode(nullptr,a,b) );
d = dprecision_rounding(c);
push_pair( d );
push_pair(c);
break;
case Bytecodes::_dneg:
@ -2585,8 +2568,7 @@ void Parse::do_one_bytecode() {
case Bytecodes::_i2f:
a = pop();
b = _gvn.transform( new ConvI2FNode(a) ) ;
c = precision_rounding(b);
push (b);
push(b);
break;
case Bytecodes::_i2d: