8312569
: RISC-V: Missing intrinsics for Math.ceil, floor, rint
Reviewed-by: luhenry, fjiang, fyang
This commit is contained in:
parent
2fd870a74f
commit
8557205a82
@ -2791,7 +2791,7 @@ public:
|
||||
if (shamt != 0) { \
|
||||
_slli(Rd, Rs1, shamt); \
|
||||
} else { \
|
||||
if (Rd != Rs1) { \
|
||||
if (Rd != Rs1) { \
|
||||
addi(Rd, Rs1, 0); \
|
||||
} \
|
||||
} \
|
||||
@ -2812,7 +2812,7 @@ public:
|
||||
if (shamt != 0) { \
|
||||
NORMAL_NAME(Rd, Rs1, shamt); \
|
||||
} else { \
|
||||
if (Rd != Rs1) { \
|
||||
if (Rd != Rs1) { \
|
||||
addi(Rd, Rs1, 0); \
|
||||
} \
|
||||
} \
|
||||
|
@ -1372,6 +1372,70 @@ void C2_MacroAssembler::minmax_fp(FloatRegister dst, FloatRegister src1, FloatRe
|
||||
bind(Done);
|
||||
}
|
||||
|
||||
// According to Java SE specification, for floating-point round operations, if
|
||||
// the input is NaN, +/-infinity, or +/-0, the same input is returned as the
|
||||
// rounded result; this differs from behavior of RISC-V fcvt instructions (which
|
||||
// round out-of-range values to the nearest max or min value), therefore special
|
||||
// handling is needed by NaN, +/-Infinity, +/-0.
|
||||
void C2_MacroAssembler::round_double_mode(FloatRegister dst, FloatRegister src, int round_mode,
|
||||
Register tmp1, Register tmp2, Register tmp3) {
|
||||
|
||||
assert_different_registers(dst, src);
|
||||
assert_different_registers(tmp1, tmp2, tmp3);
|
||||
|
||||
// Set rounding mode for conversions
|
||||
// Here we use similar modes to double->long and long->double conversions
|
||||
// Different mode for long->double conversion matter only if long value was not representable as double,
|
||||
// we got long value as a result of double->long conversion so, it is definitely representable
|
||||
RoundingMode rm;
|
||||
switch (round_mode) {
|
||||
case RoundDoubleModeNode::rmode_ceil:
|
||||
rm = RoundingMode::rup;
|
||||
break;
|
||||
case RoundDoubleModeNode::rmode_floor:
|
||||
rm = RoundingMode::rdn;
|
||||
break;
|
||||
case RoundDoubleModeNode::rmode_rint:
|
||||
rm = RoundingMode::rne;
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
// tmp1 - is a register to store double converted to long int
|
||||
// tmp2 - is a register to create constant for comparison
|
||||
// tmp3 - is a register where we store modified result of double->long conversion
|
||||
Label done, bad_val;
|
||||
|
||||
// Conversion from double to long
|
||||
fcvt_l_d(tmp1, src, rm);
|
||||
|
||||
// Generate constant (tmp2)
|
||||
// tmp2 = 100...0000
|
||||
addi(tmp2, zr, 1);
|
||||
slli(tmp2, tmp2, 63);
|
||||
|
||||
// Prepare converted long (tmp1)
|
||||
// as a result when conversion overflow we got:
|
||||
// tmp1 = 011...1111 or 100...0000
|
||||
// Convert it to: tmp3 = 100...0000
|
||||
addi(tmp3, tmp1, 1);
|
||||
andi(tmp3, tmp3, -2);
|
||||
beq(tmp3, tmp2, bad_val);
|
||||
|
||||
// Conversion from long to double
|
||||
fcvt_d_l(dst, tmp1, rm);
|
||||
// Add sign of input value to result for +/- 0 cases
|
||||
fsgnj_d(dst, dst, src);
|
||||
j(done);
|
||||
|
||||
// If got conversion overflow return src
|
||||
bind(bad_val);
|
||||
fmv_d(dst, src);
|
||||
|
||||
bind(done);
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::element_compare(Register a1, Register a2, Register result, Register cnt, Register tmp1, Register tmp2,
|
||||
VectorRegister vr1, VectorRegister vr2, VectorRegister vrs, bool islatin, Label &DONE) {
|
||||
Label loop;
|
||||
|
@ -149,6 +149,9 @@
|
||||
FloatRegister src1, FloatRegister src2,
|
||||
bool is_double, bool is_min);
|
||||
|
||||
void round_double_mode(FloatRegister dst, FloatRegister src, int round_mode,
|
||||
Register tmp1, Register tmp2, Register tmp3);
|
||||
|
||||
// intrinsic methods implemented by rvv instructions
|
||||
void string_equals_v(Register r1, Register r2,
|
||||
Register result, Register cnt1,
|
||||
|
@ -7709,6 +7709,20 @@ instruct sqrtD_reg(fRegD dst, fRegD src) %{
|
||||
ins_pipe(fp_sqrt_d);
|
||||
%}
|
||||
|
||||
// Round Instruction
|
||||
instruct roundD_reg(fRegD dst, fRegD src, immI rmode, iRegLNoSp tmp1, iRegLNoSp tmp2, iRegLNoSp tmp3) %{
|
||||
match(Set dst (RoundDoubleMode src rmode));
|
||||
ins_cost(2 * XFER_COST + BRANCH_COST);
|
||||
effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3);
|
||||
|
||||
format %{ "RoundDoubleMode $src, $rmode" %}
|
||||
ins_encode %{
|
||||
__ round_double_mode(as_FloatRegister($dst$$reg),
|
||||
as_FloatRegister($src$$reg), $rmode$$constant, $tmp1$$Register, $tmp2$$Register, $tmp3$$Register);
|
||||
%}
|
||||
ins_pipe(pipe_class_default);
|
||||
%}
|
||||
|
||||
// Arithmetic Instructions End
|
||||
|
||||
// ============================================================================
|
||||
|
Loading…
Reference in New Issue
Block a user