Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/hotspot/cpu/aarch64/assembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2962,6 +2962,18 @@ template<typename R, typename... Rx>
rf(Vn, 5), rf(Vd, 0);
}

// frecps - Floating-point Reciprocal Step
void frecps(FloatRegister Vd, FloatRegister Vn, FloatRegister Vm, SIMD_RegVariant type) {
assert(type == D || type == S, "Wrong type for frecps");
starti;
f(0b010111100, 31, 23),
f(type == D ? 1 : 0, 22);
f(1, 21);
rf(Vm, 16);
f(0b111111, 15, 10);
rf(Vn, 5), rf(Vd, 0);
}

// (long) {a, b} -> (a + b)
void addpd(FloatRegister Vd, FloatRegister Vn) {
starti;
Expand Down
8 changes: 5 additions & 3 deletions src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -832,9 +832,11 @@ void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
}
break;
case vmIntrinsics::_dlog:
// Math.log intrinsic is not implemented on AArch64 (see JDK-8210858),
// but we can still call the shared runtime.
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
if (StubRoutines::dlog() != nullptr) {
__ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
} else {
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
}
break;
case vmIntrinsics::_dlog10:
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog10), getThreadTemp(), result_reg, cc->args());
Expand Down
6 changes: 6 additions & 0 deletions src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1542,6 +1542,12 @@ class MacroAssembler: public Assembler {
FloatRegister vtmp2, FloatRegister vtmp3,
FloatRegister vtmp4, FloatRegister vtmp5);

void fast_log(FloatRegister vtmp0, FloatRegister vtmp1, FloatRegister vtmp2,
FloatRegister vtmp3, FloatRegister vtmp4, FloatRegister vtmp5,
FloatRegister tmpC1, FloatRegister tmpC2, FloatRegister tmpC3,
FloatRegister tmpC4, Register tmp1, Register tmp2,
Register tmp3, Register tmp4, Register tmp5);

void generate_dsin_dcos(bool isCos, address npio2_hw, address two_over_pi,
address pio2, address dsin_coef, address dcos_coef);
private:
Expand Down
392 changes: 392 additions & 0 deletions src/hotspot/cpu/aarch64/macroAssembler_aarch64_log.cpp

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8807,6 +8807,18 @@ class StubGenerator: public StubCodeGenerator {
return start;
}

address generate_dlog() {
__ align(CodeEntryAlignment);
StubCodeMark mark(this, "StubRoutines", "dlog");
address entry = __ pc();
FloatRegister vtmp0 = v0, vtmp1 = v1, vtmp2 = v2, vtmp3 = v3, vtmp4 = v4,
vtmp5 = v5, tmpC1 = v16, tmpC2 = v17, tmpC3 = v18, tmpC4 = v19;
Register tmp1 = r0, tmp2 = r1, tmp3 = r2, tmp4 = r3, tmp5 = r4;
__ fast_log(vtmp0, vtmp1, vtmp2, vtmp3, vtmp4, vtmp5, tmpC1, tmpC2, tmpC3,
tmpC4, tmp1, tmp2, tmp3, tmp4, tmp5);
return entry;
}

// code for comparing 16 characters of strings with Latin1 and Utf16 encoding
void compare_string_16_x_LU(Register tmpL, Register tmpU, Label &DIFF1,
Label &DIFF2) {
Expand Down Expand Up @@ -11751,6 +11763,10 @@ class StubGenerator: public StubCodeGenerator {
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C();
}

if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dlog)) {
StubRoutines::_dlog = generate_dlog();
}

if (vmIntrinsics::is_intrinsic_available(vmIntrinsics::_dsin)) {
StubRoutines::_dsin = generate_dsin_dcos(/* isCos = */ false);
}
Expand Down
43 changes: 43 additions & 0 deletions test/jdk/java/lang/Math/TestLogMinValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
* @bug 8308776
* @build Tests
* @summary Compare Math.log and StrictMath.log for Double.MIN_VALUE (denormal smallest positive) to ensure consistency.
* @run main TestLogMinValue
*/
public class TestLogMinValue {
public static void main(String[] args) {
double x = Double.MIN_VALUE; // 4.9E-324
double mathLog = Math.log(x);
double strictLog = StrictMath.log(x);
if (Double.isNaN(mathLog) || Double.isNaN(strictLog)) {
throw new AssertionError("Unexpected NaN for log(Double.MIN_VALUE)");
}
if (mathLog != strictLog) {
throw new AssertionError("Mismatch: Math.log=" + mathLog + " StrictMath.log=" + strictLog);
}
}
}
70 changes: 70 additions & 0 deletions test/jdk/java/lang/Math/TestLogMonotonicity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test 8308776
* @summary Validate monotonicity of Math.log over an ascending sequence of positive double values
* @run main TestLogMonotonicity
*/
public class TestLogMonotonicity {
public static void main(String[] args) {
double[] values = buildAscendingValues();
double prev = Double.NEGATIVE_INFINITY;
for (double v : values) {
double lv = Math.log(v);
if (Double.isNaN(lv)) {
throw new AssertionError("Unexpected NaN for Math.log(" + v + ")");
}
if (!(lv > prev)) {
throw new AssertionError("Math.log not strictly increasing: prev=" + prev + " current=" + lv + " value=" + v);
}
prev = lv;
}
}

private static double[] buildAscendingValues() {
java.util.ArrayList<Double> list = new java.util.ArrayList<>();
// Subnormal range doubling until normal threshold
double v = Double.MIN_VALUE;
while (v < Double.MIN_NORMAL) {
list.add(v);
double nv = v * 2.0;
if (nv == v)
break;
v = nv;
}
// Transition normals
list.add(Double.MIN_NORMAL);
list.add(Double.MIN_NORMAL * 2);
// Powers of two 2^1 .. 2^16
for (int i = 1; i <= 16; i++) {
list.add(Math.pow(2.0, i));
}
// Some arbitrary increasing magnitudes
list.add(Double.MAX_VALUE / 2.0); // large but avoid overflow
list.add(Double.MAX_VALUE);
double[] arr = new double[list.size()];
for (int i = 0; i < list.size(); i++) arr[i] = list.get(i);
return arr;
}
}