diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/MathCbrtTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/MathCbrtTest.java
new file mode 100644
index 000000000000..0c9594542a2d
--- /dev/null
+++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/MathCbrtTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.graal.compiler.replacements.test;
+
+import org.junit.Test;
+
+import jdk.graal.compiler.jtt.JTTTest;
+
+public class MathCbrtTest extends JTTTest {
+
+ public double cbrt(double d) {
+ return Math.cbrt(d);
+ }
+
+ @Test
+ public void testCbrt() {
+ for (double d = -3.0d; d <= 3.0D; d += 0.01D) {
+ test("cbrt", d);
+ }
+
+ double[] inputs = {Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,
+ Double.longBitsToDouble(0x7fffffffffffffffL), Double.longBitsToDouble(0xffffffffffffffffL)};
+ for (double d : inputs) {
+ test("cbrt", d);
+ }
+ }
+}
diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java
index abb68113bda6..32b4e86825b6 100644
--- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java
+++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -59,12 +59,10 @@ public void testMathSubstitutions() {
testGraph("mathSin");
testGraph("mathSqrt");
testGraph("mathTan");
+ testGraph("mathTanh");
+ testGraph("mathCbrt");
testGraph("mathAll");
- if (getReplacements().hasSubstitution(getResolvedJavaMethod(Math.class, "tanh"), getInitialOptions())) {
- testGraph("mathTanh");
- }
-
test("mathCos", value);
test("mathLog", value);
test("mathLog10", value);
@@ -72,6 +70,7 @@ public void testMathSubstitutions() {
test("mathSqrt", value);
test("mathTan", value);
test("mathTanh", value);
+ test("mathCbrt", value);
test("mathAll", value);
}
@@ -141,8 +140,12 @@ public static double mathTanh(double value) {
return Math.tanh(value);
}
+ public static double mathCbrt(double value) {
+ return Math.cbrt(value);
+ }
+
public static double mathAll(double value) {
- return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value);
+ return Math.sqrt(value) + Math.log(value) + Math.log10(value) + Math.sin(value) + Math.cos(value) + Math.tan(value) + Math.tanh(value) + Math.cbrt(value);
}
public void testSubstitution(String testMethodName, Class> holder, String methodName, boolean optional, Object[] args, Class>... intrinsicClasses) {
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java
index befb46e90cfd..2d6acfb472c0 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java
@@ -5036,6 +5036,10 @@ public final void incq(AMD64Address dst) {
AMD64MOp.INC.emit(this, OperandSize.QWORD, dst);
}
+ public final void movapd(Register dst, AMD64Address src) {
+ SSEOp.MOVAPD.emit(this, OperandSize.PD, dst, src);
+ }
+
public final void movapd(Register dst, Register src) {
SSEOp.MOVAPD.emit(this, OperandSize.PD, dst, src);
}
@@ -5299,6 +5303,10 @@ public final void orl(Register dst, int imm32) {
AMD64BinaryArithmetic.OR.getMIOpcode(OperandSize.DWORD, isByte(imm32)).emit(this, OperandSize.DWORD, dst, imm32);
}
+ public final void orpd(Register dst, Register src) {
+ SSEOp.OR.emit(this, OperandSize.PD, dst, src);
+ }
+
public final void orq(Register dst, Register src) {
AMD64BinaryArithmetic.OR.rmOp.emit(this, OperandSize.QWORD, dst, src);
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java
index c826df98f008..df33b5b53816 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java
@@ -135,6 +135,7 @@
import jdk.graal.compiler.lir.amd64.AMD64CountTrailingZerosOp;
import jdk.graal.compiler.lir.amd64.AMD64FloatToHalfFloatOp;
import jdk.graal.compiler.lir.amd64.AMD64HalfFloatToFloatOp;
+import jdk.graal.compiler.lir.amd64.AMD64MathCbrtOp;
import jdk.graal.compiler.lir.amd64.AMD64MathCopySignOp;
import jdk.graal.compiler.lir.amd64.AMD64MathCosOp;
import jdk.graal.compiler.lir.amd64.AMD64MathExpOp;
@@ -1311,6 +1312,11 @@ public Value emitMathExp(Value input) {
return new AMD64MathExpOp().emitLIRWrapper(getLIRGen(), input);
}
+ @Override
+ public Value emitMathCbrt(Value input) {
+ return new AMD64MathCbrtOp().emitLIRWrapper(getLIRGen(), input);
+ }
+
@Override
public Value emitMathPow(Value x, Value y) {
return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y);
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java
index 991f7e7496d1..24f529a66095 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java
@@ -682,6 +682,7 @@ private long getZGCAddressField(String name) {
public final long arithmeticLogAddress = getFieldValue("CompilerToVM::Data::dlog", Long.class, "address");
public final long arithmeticLog10Address = getFieldValue("CompilerToVM::Data::dlog10", Long.class, "address");
public final long arithmeticPowAddress = getFieldValue("CompilerToVM::Data::dpow", Long.class, "address");
+ public final long arithmeticCbrtAddress = getFieldValue("CompilerToVM::Data::dcbrt", Long.class, "address");
public final long fremAddress = getAddress("SharedRuntime::frem");
public final long dremAddress = getAddress("SharedRuntime::drem");
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java
index d36e373c9a5f..03ea6b157f54 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -33,6 +33,7 @@
import static jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_ALL_CALLER_SAVE_REGISTERS;
import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.LEAF;
import static jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
+import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.CBRT;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
@@ -110,6 +111,7 @@ protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotPr
link(new AMD64MathStub(LOG, options, providers, registerStubCall(LOG.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS)));
link(new AMD64MathStub(LOG10, options, providers, registerStubCall(LOG10.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS)));
link(new AMD64MathStub(POW, options, providers, registerStubCall(POW.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS)));
+ link(new AMD64MathStub(CBRT, options, providers, registerStubCall(CBRT.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS)));
} else {
super.registerMathStubs(hotSpotVMConfig, providers, options);
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java
index b819a30855e5..4c70633a354b 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -49,24 +49,16 @@ public AMD64MathStub(BinaryOperation operation, OptionValues options, HotSpotPro
}
private static String snippetName(UnaryOperation operation) {
- switch (operation) {
- case SIN:
- return "sin";
- case COS:
- return "cos";
- case TAN:
- return "tan";
- case TANH:
- return "tanh";
- case EXP:
- return "exp";
- case LOG:
- return "log";
- case LOG10:
- return "log10";
- default:
- throw GraalError.shouldNotReachHere("Unknown operation " + operation); // ExcludeFromJacocoGeneratedReport
- }
+ return switch (operation) {
+ case SIN -> "sin";
+ case COS -> "cos";
+ case TAN -> "tan";
+ case TANH -> "tanh";
+ case EXP -> "exp";
+ case LOG -> "log";
+ case LOG10 -> "log10";
+ case CBRT -> "cbrt";
+ };
}
private static String snippetName(BinaryOperation operation) {
@@ -115,4 +107,9 @@ private static double exp(double value) {
private static double pow(double value1, double value2) {
return BinaryMathIntrinsicNode.compute(value1, value2, BinaryOperation.POW);
}
+
+ @Snippet
+ private static double cbrt(double value) {
+ return UnaryMathIntrinsicNode.compute(value, UnaryOperation.CBRT);
+ }
}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java
index 59ceb0ace38d..f8cc456c57dc 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java
@@ -103,6 +103,7 @@
import static jdk.graal.compiler.hotspot.stubs.UnwindExceptionToCallerStub.EXCEPTION_HANDLER_FOR_RETURN_ADDRESS;
import static jdk.graal.compiler.nodes.java.ForeignCallDescriptors.REGISTER_FINALIZER;
import static jdk.graal.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation.POW;
+import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.CBRT;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
@@ -706,6 +707,9 @@ protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotPr
if (hotSpotVMConfig.arithmeticTanhAddress != 0L) {
registerForeignCall(createDescriptor(TANH.foreignCallSignature, LEAF, NO_SIDE_EFFECT, NO_LOCATIONS), hotSpotVMConfig.arithmeticTanhAddress, NativeCall);
}
+ if (hotSpotVMConfig.arithmeticCbrtAddress != 0L) {
+ registerForeignCall(createDescriptor(CBRT.foreignCallSignature, LEAF, NO_SIDE_EFFECT, NO_LOCATIONS), hotSpotVMConfig.arithmeticCbrtAddress, NativeCall);
+ }
}
private void registerSnippetStubs(HotSpotProviders providers, OptionValues options) {
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java
index 96b3dba0c226..4d37d78ee974 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java
@@ -154,6 +154,8 @@ public UnimplementedGraalIntrinsics(Architecture arch) {
// HotSpot runtime does not implement C2Compiler::is_intrinsic_supported for the
// following intrinsics properly
add(ignore,
+ // JDK-8355644
+ "java/lang/Math.cbrt(D)D",
// JDK-8338694
"java/lang/Math.tanh(D)D",
// JDK-8309130
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64MathCbrtOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64MathCbrtOp.java
new file mode 100644
index 000000000000..70c5b5a35c24
--- /dev/null
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64MathCbrtOp.java
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, Intel Corporation. All rights reserved.
+ * Intel Math Library (LIBM) Source Code
+ * 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.graal.compiler.lir.amd64;
+
+import static jdk.graal.compiler.lir.amd64.AMD64LIRHelper.pointerConstant;
+import static jdk.graal.compiler.lir.amd64.AMD64LIRHelper.recordExternalAddress;
+import static jdk.vm.ci.amd64.AMD64.r8;
+import static jdk.vm.ci.amd64.AMD64.r9;
+import static jdk.vm.ci.amd64.AMD64.rax;
+import static jdk.vm.ci.amd64.AMD64.rcx;
+import static jdk.vm.ci.amd64.AMD64.rdx;
+import static jdk.vm.ci.amd64.AMD64.rsp;
+import static jdk.vm.ci.amd64.AMD64.xmm0;
+import static jdk.vm.ci.amd64.AMD64.xmm1;
+import static jdk.vm.ci.amd64.AMD64.xmm2;
+import static jdk.vm.ci.amd64.AMD64.xmm3;
+import static jdk.vm.ci.amd64.AMD64.xmm4;
+import static jdk.vm.ci.amd64.AMD64.xmm5;
+import static jdk.vm.ci.amd64.AMD64.xmm6;
+import static jdk.vm.ci.amd64.AMD64.xmm7;
+
+import jdk.graal.compiler.asm.Label;
+import jdk.graal.compiler.asm.amd64.AMD64Address;
+import jdk.graal.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
+import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
+import jdk.graal.compiler.core.common.Stride;
+import jdk.graal.compiler.lir.LIRInstructionClass;
+import jdk.graal.compiler.lir.SyncPort;
+import jdk.graal.compiler.lir.asm.ArrayDataPointerConstant;
+import jdk.graal.compiler.lir.asm.CompilationResultBuilder;
+
+/**
+ *
+ * ALGORITHM DESCRIPTION
+ * ---------------------
+ *
+ * x=2^{3*k+j} * 1.b1 b2 ... b5 b6 ... b52
+ * Let r=(x*2^{-3k-j} - 1.b1 b2 ... b5 1)* rcp[b1 b2 ..b5],
+ * where rcp[b1 b2 .. b5]=1/(1.b1 b2 b3 b4 b5 1) in double precision
+ * cbrt(2^j * 1. b1 b2 .. b5 1) is approximated as T[j][b1..b5]+D[j][b1..b5]
+ * (T stores the high 53 bits, D stores the low order bits)
+ * Result=2^k*T+(2^k*T*r)*P+2^k*D
+ * where P=p1+p2*r+..+p8*r^7
+ *
+ * Special cases:
+ * cbrt(NaN) = quiet NaN
+ * cbrt(+/-INF) = +/-INF
+ * cbrt(+/-0) = +/-0
+ *
+ */
+// @formatter:off
+@SyncPort(from = "https://github.com/openjdk/jdk/blob/83cb0c6de5988de526545d0926c2c6ef60efc1c7/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp#L30-L364",
+ sha1 = "1cf43819053aac54cbe343f9b8a8bfcc3e3dd6c8")
+// @formatter:on
+public final class AMD64MathCbrtOp extends AMD64MathIntrinsicUnaryOp {
+
+ public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64MathCbrtOp.class);
+
+ public AMD64MathCbrtOp() {
+ super(TYPE, /* GPR */ rax, rcx, rdx, r8, r9,
+ /* XMM */ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7);
+ }
+
+ private static ArrayDataPointerConstant sigMask = pointerConstant(16, new int[]{
+ 0x00000000, 0x000fc000
+ });
+
+ private static ArrayDataPointerConstant expMask = pointerConstant(16, new int[]{
+ 0x00000000, 0xbff00000
+ });
+
+ private static ArrayDataPointerConstant expMsk2 = pointerConstant(16, new int[]{
+ 0x00000000, 0xbff04000
+ });
+
+ private static ArrayDataPointerConstant expMsk3 = pointerConstant(16, new int[]{
+ 0xffffffff, 0x000fffff
+ });
+
+ private static ArrayDataPointerConstant scale63 = pointerConstant(16, new int[]{
+ 0x00000000, 0x43e00000
+ });
+
+ private static ArrayDataPointerConstant zeron = pointerConstant(16, new int[]{
+ 0x00000000, 0x80000000
+ });
+
+ private static ArrayDataPointerConstant inf = pointerConstant(16, new int[]{
+ 0x00000000, 0x7ff00000
+ });
+
+ private static ArrayDataPointerConstant negInf = pointerConstant(16, new int[]{
+ 0x00000000, 0xfff00000
+ });
+
+ private static ArrayDataPointerConstant coeffTable = pointerConstant(16, new int[]{
+ 0x5c9cc8e7, 0xbf9036de, 0xd2b3183b, 0xbfa511e8,
+ });
+
+ private static ArrayDataPointerConstant coeffTable16 = pointerConstant(16, new int[]{
+ 0x6221a247, 0xbf98090d, 0x1c71c71c, 0xbfbc71c7,
+ });
+
+ private static ArrayDataPointerConstant coeffTable32 = pointerConstant(16, new int[]{
+ 0xd588f115, 0x3f93750a, 0x3c0ca458, 0x3faf9add
+ });
+
+ private static ArrayDataPointerConstant coeffTable48 = pointerConstant(16, new int[]{
+ 0x3506ac12, 0x3f9ee711, 0x55555555, 0x3fd55555
+ });
+
+ private static ArrayDataPointerConstant rcpTable = pointerConstant(16, new int[]{
+ 0x1f81f820, 0xbfef81f8, 0xabf0b767, 0xbfee9131, 0x76b981db, 0xbfedae60,
+ 0x89039b0b, 0xbfecd856, 0x0381c0e0, 0xbfec0e07, 0xb4e81b4f, 0xbfeb4e81,
+ 0x606a63be, 0xbfea98ef, 0x951033d9, 0xbfe9ec8e, 0xfcd6e9e0, 0xbfe948b0,
+ 0x0f6bf3aa, 0xbfe8acb9, 0x18181818, 0xbfe81818, 0x8178a4c8, 0xbfe78a4c,
+ 0x5c0b8170, 0xbfe702e0, 0x16816817, 0xbfe68168, 0x60581606, 0xbfe60581,
+ 0x308158ed, 0xbfe58ed2, 0xeae2f815, 0xbfe51d07, 0xa052bf5b, 0xbfe4afd6,
+ 0x6562d9fb, 0xbfe446f8, 0xbce4a902, 0xbfe3e22c, 0x13813814, 0xbfe38138,
+ 0x4a2b10bf, 0xbfe323e3, 0x4d812ca0, 0xbfe2c9fb, 0xb8812735, 0xbfe27350,
+ 0x8121fb78, 0xbfe21fb7, 0xada2811d, 0xbfe1cf06, 0x11811812, 0xbfe18118,
+ 0x1135c811, 0xbfe135c8, 0x6be69c90, 0xbfe0ecf5, 0x0a6810a7, 0xbfe0a681,
+ 0xd2f1a9fc, 0xbfe0624d, 0x81020408, 0xbfe02040
+ });
+
+ private static ArrayDataPointerConstant cbrtTable = pointerConstant(16, new int[]{
+ 0x221d4c97, 0x3ff01539, 0x771a2e33, 0x3ff03f06, 0xe629d671, 0x3ff06800,
+ 0x8731deb2, 0x3ff09032, 0xb1bd64ac, 0x3ff0b7a4, 0x1024fb87, 0x3ff0de60,
+ 0xb0597000, 0x3ff1046c, 0x12a9ba9b, 0x3ff129d2, 0x36cdaf38, 0x3ff14e97,
+ 0xa772f507, 0x3ff172c2, 0x848001d3, 0x3ff1965a, 0x8c38c55d, 0x3ff1b964,
+ 0x236a0c45, 0x3ff1dbe6, 0x5cbb1f9f, 0x3ff1fde4, 0xff409042, 0x3ff21f63,
+ 0x8c6746e5, 0x3ff24069, 0x454bb99b, 0x3ff260f9, 0x2f8e7073, 0x3ff28117,
+ 0x19b4b6d0, 0x3ff2a0c7, 0x9f2263ec, 0x3ff2c00c, 0x2bb7fb78, 0x3ff2deeb,
+ 0xff1efbbc, 0x3ff2fd65, 0x2fccf6a2, 0x3ff31b80, 0xadc50708, 0x3ff3393c,
+ 0x451e4c2a, 0x3ff3569e, 0xa0554cde, 0x3ff373a7, 0x4a6d76ce, 0x3ff3905b,
+ 0xb0e756b6, 0x3ff3acbb, 0x258fa340, 0x3ff3c8cb, 0xe02ac0ce, 0x3ff3e48b,
+ 0x00000000, 0x3ff40000, 0x8d47800e, 0x3ff41b29, 0x4b34d9b2, 0x3ff44360,
+ 0x20906571, 0x3ff4780b, 0x3ee06706, 0x3ff4abac, 0x5da66b8d, 0x3ff4de50,
+ 0x420a5c07, 0x3ff51003, 0xd6fd11c1, 0x3ff540cf, 0x4260716b, 0x3ff570c0,
+ 0xf7a45f38, 0x3ff59fdd, 0xc83539df, 0x3ff5ce31, 0xf20966a4, 0x3ff5fbc3,
+ 0x2c8f1b70, 0x3ff6289c, 0xb4316dcf, 0x3ff654c1, 0x54a34e44, 0x3ff6803b,
+ 0x72182659, 0x3ff6ab0f, 0x118c08bc, 0x3ff6d544, 0xe0388d4a, 0x3ff6fede,
+ 0x3a4f645e, 0x3ff727e5, 0x31104114, 0x3ff7505c, 0x904cd549, 0x3ff77848,
+ 0xe36b2534, 0x3ff79fae, 0x79f4605b, 0x3ff7c693, 0x6bbca391, 0x3ff7ecfa,
+ 0x9cae7eb9, 0x3ff812e7, 0xc043c71d, 0x3ff8385e, 0x5cb41b9d, 0x3ff85d63,
+ 0xcde083db, 0x3ff881f8, 0x4802b8a8, 0x3ff8a622, 0xda25e5e4, 0x3ff8c9e2,
+ 0x706e1010, 0x3ff8ed3d, 0xd632b6df, 0x3ff91034, 0xb7f0cf2d, 0x3ff932cb,
+ 0xa517bf3a, 0x3ff95504, 0x34f8bb19, 0x3ff987af, 0x8337b317, 0x3ff9ca0a,
+ 0x09cc13d5, 0x3ffa0b17, 0xce6419ed, 0x3ffa4ae4, 0xa5567031, 0x3ffa8982,
+ 0x500ab570, 0x3ffac6fe, 0x97a15a17, 0x3ffb0364, 0x64671755, 0x3ffb3ec1,
+ 0xd288c46f, 0x3ffb791f, 0x44693be4, 0x3ffbb28a, 0x72eb6e31, 0x3ffbeb0a,
+ 0x7bf5f697, 0x3ffc22a9, 0xef6af983, 0x3ffc596f, 0xdac655a3, 0x3ffc8f65,
+ 0xd38ce8d9, 0x3ffcc492, 0x00b19367, 0x3ffcf8fe, 0x230f8709, 0x3ffd2cae,
+ 0x9d15208f, 0x3ffd5fa9, 0x79b6e505, 0x3ffd91f6, 0x72bf2302, 0x3ffdc39a,
+ 0xf68c1570, 0x3ffdf49a, 0x2d4c23b8, 0x3ffe24fd, 0xfdc5ec73, 0x3ffe54c5,
+ 0x11b81dbb, 0x3ffe83fa, 0xd9dbaf25, 0x3ffeb29d, 0x9191d374, 0x3ffee0b5,
+ 0x4245e4bf, 0x3fff0e45, 0xc68a9dd3, 0x3fff3b50, 0xccf922dc, 0x3fff67db,
+ 0xdad7a4a6, 0x3fff93e9, 0x4e8cc9cb, 0x3fffbf7e, 0x61e47cd3, 0x3fffea9c
+ });
+
+ private static ArrayDataPointerConstant dTable = pointerConstant(16, new int[]{
+ 0xf173d5fa, 0x3c76ee36, 0x45055704, 0x3c95b62d, 0x51ee3f07, 0x3ca2545b,
+ 0xa7706e18, 0x3c9c65f4, 0xdf1025a1, 0x3c63b83f, 0xb8dec2c5, 0x3ca67428,
+ 0x03e33ea6, 0x3ca1823d, 0xa06e6c52, 0x3ca241d3, 0xefa7e815, 0x3ca8b4e1,
+ 0x4e754fd0, 0x3cadeac4, 0x3d7c04c0, 0x3c71cc82, 0xc264f127, 0x3c953dc9,
+ 0x34d5c5a7, 0x3c93b5f7, 0xb9a7b902, 0x3c7366a3, 0x6433dd6c, 0x3caac888,
+ 0x4f401711, 0x3c987a4c, 0x1bbe943f, 0x3c9fab9f, 0xfd6ac93c, 0x3ca0c4b5,
+ 0x766f1035, 0x3ca90835, 0x2ce13c95, 0x3ca09fd9, 0x8418c8d8, 0x3cadc143,
+ 0xff474261, 0x3c8dc87d, 0x5cd783d3, 0x3c8f8872, 0xe7d0c8aa, 0x3caec35d,
+ 0xdba49538, 0x3ca3943b, 0x2b203947, 0x3ca92195, 0xafe6f86c, 0x3c59f556,
+ 0x3195a5f9, 0x3caadc99, 0x3d770e65, 0x3ca41943, 0xa36b97ea, 0x3ca76b6e,
+ 0xaaaaaaab, 0x3bd46aaa, 0xfee9d063, 0x3c637d40, 0xf514c24e, 0x3c89f356,
+ 0x670030e9, 0x3c953f22, 0xa173c1cf, 0x3caea671, 0x3fbcc1dd, 0x3c841d58,
+ 0x29b9b818, 0x3c9648f0, 0xad202ab4, 0x3ca1a66d, 0xf2d6b269, 0x3ca7b07b,
+ 0x017dc4ad, 0x3c836a36, 0xd6b16f60, 0x3c8b726b, 0xc2bc701d, 0x3cabfe18,
+ 0x1dfe451f, 0x3c7e799d, 0x7e7b5452, 0x3caddf5a, 0xea15c5e5, 0x3c734d90,
+ 0xa6558f7b, 0x3c8f4cbb, 0x4f4d361a, 0x3c9d473a, 0xf06b5ecf, 0x3c87e2d6,
+ 0xdc49b5f3, 0x3ca5f6f5, 0x0f5a41f1, 0x3ca16024, 0xc062c2bc, 0x3ca3586c,
+ 0x0df45d94, 0x3ca0c6a9, 0xeef4e10b, 0x3ca2703c, 0x74215c62, 0x3ca99f3e,
+ 0x286f88d2, 0x3cafa5ef, 0xb7d00b1f, 0x3c99239e, 0x8ff8e50c, 0x3cabc642,
+ 0x0a756b50, 0x3ca33971, 0xbe93d5dc, 0x3c389058, 0x7b752d97, 0x3c8e08ee,
+ 0x0fff0a3f, 0x3c9a2fed, 0x37eac5df, 0x3ca42034, 0x6c4969df, 0x3ca35668,
+ 0xf5860fa5, 0x3ca082ae, 0x99b322b6, 0x3c62cf11, 0x933e42d8, 0x3c7ac44e,
+ 0x0761e377, 0x3c975f68, 0x4b704cc9, 0x3c7c5adf, 0xcb8394dc, 0x3ca0f9ae,
+ 0x3e08f0f9, 0x3c9158c1, 0xcfa3f556, 0x3c9c7516, 0xf6cb01cd, 0x3c91d9c1,
+ 0xe811c1da, 0x3c9da58f, 0xea9036db, 0x3c2dcd9d, 0xb18fab04, 0x3c8015a8,
+ 0x92316223, 0x3cad4c55, 0xbe291e10, 0x3c8c6a0d, 0xfc9476ab, 0x3c8c615d,
+ 0x9b9bca75, 0x3cace0d7, 0x7ecc4726, 0x3ca4614a, 0x312152ee, 0x3cacd427,
+ 0x811960ca, 0x3cac1ba1, 0xa557fd24, 0x3c6514ca, 0xf5cdf826, 0x3ca712cc,
+ 0x75cdbea6, 0x3c9d93a5, 0xf3f3450c, 0x3ca90aaf, 0x071ba369, 0x3c85382f,
+ 0xcf26ae90, 0x3ca87e97, 0x75933097, 0x3c86da5c, 0x309c2b19, 0x3ca61791,
+ 0x90d5990b, 0x3ca44210, 0xf22ac222, 0x3c9a5f49, 0x0411eef9, 0x3cac502e,
+ 0x839809ae, 0x3c93d12a, 0x468a4418, 0x3ca46c91, 0x088afcdb, 0x3c9f1c33
+ });
+
+ @Override
+ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+ // Registers:
+ // input: xmm0
+ // scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
+ // rax, rdx, rcx
+ Label l2TAGPACKET001 = new Label();
+ Label l2TAGPACKET101 = new Label();
+ Label l2TAGPACKET201 = new Label();
+ Label l2TAGPACKET301 = new Label();
+ Label l2TAGPACKET401 = new Label();
+ Label l2TAGPACKET501 = new Label();
+ Label l2TAGPACKET601 = new Label();
+ Label lB11 = new Label();
+ Label lB12 = new Label();
+ Label lB14 = new Label();
+
+ masm.bind(lB11);
+ masm.subq(rsp, 24);
+ masm.movsd(new AMD64Address(rsp), xmm0);
+
+ masm.bind(lB12);
+ masm.movq(xmm7, xmm0);
+ masm.movl(rdx, 0x7ff00);
+ masm.movsd(xmm5, recordExternalAddress(crb, expMsk3));
+ masm.movsd(xmm3, recordExternalAddress(crb, expMsk2));
+ masm.psrlq(xmm7, 44);
+ masm.pextrw(rcx, xmm7, 0);
+ masm.movdl(rax, xmm7);
+ masm.movsd(xmm1, recordExternalAddress(crb, expMask));
+ masm.movsd(xmm2, recordExternalAddress(crb, sigMask));
+ masm.andl(rcx, 0xf8);
+ masm.leaq(r8, recordExternalAddress(crb, rcpTable));
+ masm.movsd(xmm4, new AMD64Address(rcx, r8, Stride.S1));
+ masm.movq(r9, rax);
+ masm.andl(rdx, rax);
+ // Branch only if |x| is denormalized
+ masm.cmplAndJcc(rdx, 0, ConditionFlag.Equal, l2TAGPACKET001, false);
+ // Branch only if |x| is INF or NaN
+ masm.cmplAndJcc(rdx, 0x7ff00, ConditionFlag.Equal, l2TAGPACKET101, false);
+ masm.shrl(rdx, 8);
+ masm.shrq(r9, 8);
+ masm.andpd(xmm2, xmm0);
+ masm.andpd(xmm0, xmm5);
+ masm.orpd(xmm3, xmm2);
+ masm.orpd(xmm1, xmm0);
+ masm.movapd(xmm5, recordExternalAddress(crb, coeffTable));
+ masm.movl(rax, 0x1556);
+ masm.movapd(xmm6, recordExternalAddress(crb, coeffTable16));
+ masm.mull(rdx);
+ masm.movq(rdx, r9);
+ masm.andq(r9, 0x7ff);
+ masm.shrl(rax, 14);
+ masm.andl(rdx, 0x800);
+ masm.subq(r9, rax);
+ masm.subq(r9, rax);
+ masm.subq(r9, rax);
+ masm.shlq(r9, 8);
+ masm.addl(rax, 0x2aa);
+ masm.orl(rax, rdx);
+ masm.movdl(xmm7, rax);
+ masm.addq(rcx, r9);
+ masm.psllq(xmm7, 52);
+
+ masm.bind(l2TAGPACKET201);
+ masm.movapd(xmm2, recordExternalAddress(crb, coeffTable32));
+ masm.movapd(xmm0, recordExternalAddress(crb, coeffTable48));
+ masm.subsd(xmm1, xmm3);
+ masm.movq(xmm3, xmm7);
+ masm.leaq(r8, recordExternalAddress(crb, cbrtTable));
+ masm.mulsd(xmm7, new AMD64Address(rcx, r8, Stride.S1));
+ masm.mulsd(xmm1, xmm4);
+ masm.leaq(r8, recordExternalAddress(crb, dTable));
+ masm.mulsd(xmm3, new AMD64Address(rcx, r8, Stride.S1));
+ masm.movapd(xmm4, xmm1);
+ masm.unpcklpd(xmm1, xmm1);
+ masm.mulpd(xmm5, xmm1);
+ masm.mulpd(xmm6, xmm1);
+ masm.mulpd(xmm1, xmm1);
+ masm.addpd(xmm2, xmm5);
+ masm.addpd(xmm0, xmm6);
+ masm.mulpd(xmm2, xmm1);
+ masm.mulpd(xmm1, xmm1);
+ masm.mulsd(xmm4, xmm7);
+ masm.addpd(xmm0, xmm2);
+ masm.mulsd(xmm1, xmm0);
+ masm.unpckhpd(xmm0, xmm0);
+ masm.addsd(xmm0, xmm1);
+ masm.mulsd(xmm0, xmm4);
+ masm.addsd(xmm0, xmm3);
+ masm.addsd(xmm0, xmm7);
+ masm.jmp(lB14);
+
+ masm.bind(l2TAGPACKET001);
+ masm.mulsd(xmm0, recordExternalAddress(crb, scale63));
+ masm.movq(xmm7, xmm0);
+ masm.movl(rdx, 0x7ff00);
+ masm.psrlq(xmm7, 44);
+ masm.pextrw(rcx, xmm7, 0);
+ masm.movdl(rax, xmm7);
+ masm.andl(rcx, 0xf8);
+ masm.leaq(r8, recordExternalAddress(crb, rcpTable));
+ masm.movsd(xmm4, new AMD64Address(rcx, r8, Stride.S1));
+ masm.movq(r9, rax);
+ masm.andl(rdx, rax);
+ masm.shrl(rdx, 8);
+ masm.shrq(r9, 8);
+ // Branch only if |x| is zero
+ masm.cmplAndJcc(rdx, 0, ConditionFlag.Equal, l2TAGPACKET301, false);
+ masm.andpd(xmm2, xmm0);
+ masm.andpd(xmm0, xmm5);
+ masm.orpd(xmm3, xmm2);
+ masm.orpd(xmm1, xmm0);
+ masm.movapd(xmm5, recordExternalAddress(crb, coeffTable));
+ masm.movl(rax, 0x1556);
+ masm.movapd(xmm6, recordExternalAddress(crb, coeffTable16));
+ masm.mull(rdx);
+ masm.movq(rdx, r9);
+ masm.andq(r9, 0x7ff);
+ masm.shrl(rax, 14);
+ masm.andl(rdx, 0x800);
+ masm.subq(r9, rax);
+ masm.subq(r9, rax);
+ masm.subq(r9, rax);
+ masm.shlq(r9, 8);
+ masm.addl(rax, 0x295);
+ masm.orl(rax, rdx);
+ masm.movdl(xmm7, rax);
+ masm.addq(rcx, r9);
+ masm.psllq(xmm7, 52);
+ masm.jmp(l2TAGPACKET201);
+
+ masm.bind(l2TAGPACKET301);
+ // Branch only if x is negative zero
+ masm.cmpqAndJcc(r9, 0, ConditionFlag.NotEqual, l2TAGPACKET401, false);
+ masm.xorpd(xmm0, xmm0);
+ masm.jmp(lB14);
+
+ masm.bind(l2TAGPACKET401);
+ masm.movsd(xmm0, recordExternalAddress(crb, zeron));
+ masm.jmp(lB14);
+
+ masm.bind(l2TAGPACKET101);
+ masm.movl(rax, new AMD64Address(rsp, 4));
+ masm.movl(rdx, new AMD64Address(rsp));
+ masm.movl(rcx, rax);
+ masm.andl(rcx, 0x7fffffff);
+ // Branch only if |x| is NaN
+ masm.cmplAndJcc(rcx, 0x7ff00000, ConditionFlag.Above, l2TAGPACKET501, false);
+ // Branch only if |x| is NaN
+ masm.cmplAndJcc(rdx, 0, ConditionFlag.NotEqual, l2TAGPACKET501, false);
+ // Branch only if x is negative INF
+ masm.cmplAndJcc(rax, 0x7ff00000, ConditionFlag.NotEqual, l2TAGPACKET601, false);
+ masm.movsd(xmm0, recordExternalAddress(crb, inf));
+ masm.jmp(lB14);
+
+ masm.bind(l2TAGPACKET601);
+ masm.movsd(xmm0, recordExternalAddress(crb, negInf));
+ masm.jmp(lB14);
+
+ masm.bind(l2TAGPACKET501);
+ masm.movsd(xmm0, new AMD64Address(rsp));
+ masm.addsd(xmm0, xmm0);
+ masm.movq(new AMD64Address(rsp, 8), xmm0);
+
+ masm.bind(lB14);
+ masm.addq(rsp, 24);
+ }
+}
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java
index 5612910057fe..dd21e5d7d1af 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -174,6 +174,11 @@ default Value emitMathExp(Value input) {
throw GraalError.unimplemented("No specialized implementation available"); // ExcludeFromJacocoGeneratedReport
}
+ @SuppressWarnings("unused")
+ default Value emitMathCbrt(Value input) {
+ throw GraalError.unimplemented("No specialized implementation available"); // ExcludeFromJacocoGeneratedReport
+ }
+
@SuppressWarnings("unused")
default Value emitMathPow(Value x, Value y) {
throw GraalError.unimplemented("No specialized implementation available"); // ExcludeFromJacocoGeneratedReport
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java
index c61c69ec0139..31603eb87b32 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java
@@ -25,6 +25,7 @@
package jdk.graal.compiler.replacements.amd64;
import static jdk.graal.compiler.nodes.calc.FloatTypeTestNode.FloatTypeTestOp.IS_INFINITE;
+import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.CBRT;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.COS;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.EXP;
import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG;
@@ -189,6 +190,7 @@ private static void registerMathPlugins(InvocationPlugins plugins, AMD64 arch, R
registerUnaryMath(r, "cos", COS);
registerUnaryMath(r, "tan", TAN);
registerUnaryMath(r, "tanh", TANH);
+ registerUnaryMath(r, "cbrt", CBRT);
registerFMA(r, arch);
registerMinMax(r, arch);
diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java
index 908af0a1c64a..385464b54ea6 100644
--- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java
+++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -33,7 +33,6 @@
import jdk.graal.compiler.core.common.type.Stamp;
import jdk.graal.compiler.core.common.type.StampFactory;
import jdk.graal.compiler.debug.Assertions;
-import jdk.graal.compiler.debug.GraalError;
import jdk.graal.compiler.graph.NodeClass;
import jdk.graal.compiler.lir.gen.ArithmeticLIRGeneratorTool;
import jdk.graal.compiler.nodeinfo.NodeInfo;
@@ -52,7 +51,7 @@
public final class UnaryMathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable, Lowerable {
public static final NodeClass TYPE = NodeClass.create(UnaryMathIntrinsicNode.class);
- protected final UnaryOperation operation;
+ private final UnaryOperation operation;
public enum UnaryOperation {
LOG(new ForeignCallSignature("arithmeticLog", double.class, double.class)),
@@ -61,7 +60,8 @@ public enum UnaryOperation {
COS(new ForeignCallSignature("arithmeticCos", double.class, double.class)),
TAN(new ForeignCallSignature("arithmeticTan", double.class, double.class)),
TANH(new ForeignCallSignature("arithmeticTanh", double.class, double.class)),
- EXP(new ForeignCallSignature("arithmeticExp", double.class, double.class));
+ EXP(new ForeignCallSignature("arithmeticExp", double.class, double.class)),
+ CBRT(new ForeignCallSignature("arithmeticCbrt", double.class, double.class));
public final ForeignCallSignature foreignCallSignature;
@@ -70,32 +70,23 @@ public enum UnaryOperation {
}
public static double compute(UnaryOperation op, double value) {
- switch (op) {
- case LOG:
- return Math.log(value);
- case LOG10:
- return Math.log10(value);
- case EXP:
- return Math.exp(value);
- case SIN:
- return Math.sin(value);
- case COS:
- return Math.cos(value);
- case TAN:
- return Math.tan(value);
- case TANH:
- return Math.tanh(value);
- default:
- throw new GraalError("unknown op %s", op);
- }
+ return switch (op) {
+ case LOG -> Math.log(value);
+ case LOG10 -> Math.log10(value);
+ case EXP -> Math.exp(value);
+ case SIN -> Math.sin(value);
+ case COS -> Math.cos(value);
+ case TAN -> Math.tan(value);
+ case TANH -> Math.tanh(value);
+ case CBRT -> Math.cbrt(value);
+ };
}
public static Stamp computeStamp(UnaryOperation op, Stamp valueStamp) {
if (valueStamp.isEmpty()) {
return StampFactory.forKind(JavaKind.Double).empty();
}
- if (valueStamp instanceof FloatStamp) {
- FloatStamp floatStamp = (FloatStamp) valueStamp;
+ if (valueStamp instanceof FloatStamp floatStamp) {
switch (op) {
case TANH:
case COS:
@@ -118,13 +109,13 @@ public static Stamp computeStamp(UnaryOperation op, Stamp valueStamp) {
boolean nonNaN = floatStamp.lowerBound() >= 0.0 && floatStamp.isNonNaN();
return StampFactory.forFloat(JavaKind.Double, lowerBound, upperBound, nonNaN);
}
+ case CBRT:
case EXP: {
- double lowerBound = Math.exp(floatStamp.lowerBound());
- double upperBound = Math.exp(floatStamp.upperBound());
+ double lowerBound = compute(op, floatStamp.lowerBound());
+ double upperBound = compute(op, floatStamp.upperBound());
boolean nonNaN = floatStamp.isNonNaN();
return StampFactory.forFloat(JavaKind.Double, lowerBound, upperBound, nonNaN);
}
-
}
}
return StampFactory.forKind(JavaKind.Double);
@@ -144,7 +135,7 @@ public static ValueNode create(ValueNode value, UnaryOperation op) {
return new UnaryMathIntrinsicNode(value, op);
}
- protected static ValueNode tryConstantFold(ValueNode value, UnaryOperation op) {
+ private static ValueNode tryConstantFold(ValueNode value, UnaryOperation op) {
if (value.isConstant()) {
return ConstantNode.forDouble(UnaryOperation.compute(op, value.asJavaConstant().asDouble()));
}
@@ -167,32 +158,16 @@ public Stamp foldStamp(Stamp valueStamp) {
public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) {
// We can only reach here in the math stubs
Value input = nodeValueMap.operand(getValue());
- Value result;
- switch (getOperation()) {
- case LOG:
- result = gen.emitMathLog(input, false);
- break;
- case LOG10:
- result = gen.emitMathLog(input, true);
- break;
- case EXP:
- result = gen.emitMathExp(input);
- break;
- case SIN:
- result = gen.emitMathSin(input);
- break;
- case COS:
- result = gen.emitMathCos(input);
- break;
- case TAN:
- result = gen.emitMathTan(input);
- break;
- case TANH:
- result = gen.emitMathTanh(input);
- break;
- default:
- throw GraalError.shouldNotReachHereUnexpectedValue(getOperation()); // ExcludeFromJacocoGeneratedReport
- }
+ Value result = switch (getOperation()) {
+ case LOG -> gen.emitMathLog(input, false);
+ case LOG10 -> gen.emitMathLog(input, true);
+ case EXP -> gen.emitMathExp(input);
+ case SIN -> gen.emitMathSin(input);
+ case COS -> gen.emitMathCos(input);
+ case TAN -> gen.emitMathTan(input);
+ case TANH -> gen.emitMathTanh(input);
+ case CBRT -> gen.emitMathCbrt(input);
+ };
nodeValueMap.setResult(this, result);
}
diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java
index f3f6713ef613..0eca9dab356f 100644
--- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java
+++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java
@@ -62,9 +62,10 @@ public class SnippetRuntime {
private static final SubstrateForeignCallDescriptor ARITHMETIC_LOG10 = findForeignJdkCall(UnaryOperation.LOG10.foreignCallSignature.getName(), Math.class, "log10", NO_SIDE_EFFECT, true, true);
private static final SubstrateForeignCallDescriptor ARITHMETIC_EXP = findForeignJdkCall(UnaryOperation.EXP.foreignCallSignature.getName(), Math.class, "exp", NO_SIDE_EFFECT, true, true);
private static final SubstrateForeignCallDescriptor ARITHMETIC_POW = findForeignJdkCall(BinaryOperation.POW.foreignCallSignature.getName(), Math.class, "pow", NO_SIDE_EFFECT, true, true);
+ private static final SubstrateForeignCallDescriptor ARITHMETIC_CBRT = findForeignJdkCall(UnaryOperation.CBRT.foreignCallSignature.getName(), Math.class, "cbrt", NO_SIDE_EFFECT, true, true);
private static final SubstrateForeignCallDescriptor[] FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{UNSUPPORTED_FEATURE, REGISTER_FINALIZER, ARITHMETIC_SIN, ARITHMETIC_COS, ARITHMETIC_TAN,
- ARITHMETIC_TANH, ARITHMETIC_LOG, ARITHMETIC_LOG10, ARITHMETIC_EXP, ARITHMETIC_POW};
+ ARITHMETIC_TANH, ARITHMETIC_LOG, ARITHMETIC_LOG10, ARITHMETIC_EXP, ARITHMETIC_POW, ARITHMETIC_CBRT};
public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) {
foreignCalls.register(FOREIGN_CALLS);
diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java
index a3c6a4136f87..befd0374e052 100644
--- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java
+++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java
@@ -65,6 +65,7 @@ public class WasmImports {
public static final ImportDescriptor.Function F64Tanh = new ImportDescriptor.Function(MODULE_COMPAT, "f64tanh", TypeUse.forUnary(f64, f64), "Math.tanh");
public static final ImportDescriptor.Function F64Exp = new ImportDescriptor.Function(MODULE_COMPAT, "f64exp", TypeUse.forUnary(f64, f64), "Math.exp");
public static final ImportDescriptor.Function F64Pow = new ImportDescriptor.Function(MODULE_COMPAT, "f64pow", TypeUse.forBinary(f64, f64, f64), "Math.pow");
+ public static final ImportDescriptor.Function F64Cbrt = new ImportDescriptor.Function(MODULE_COMPAT, "f64cbrt", TypeUse.forBinary(f64, f64, f64), "Math.cbrt");
/**
* Signature: {@code printBytes(fd, bytePtr, numBytes)}.
diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java
index c1d93995090b..e2e263cd0149 100644
--- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java
+++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java
@@ -942,6 +942,7 @@ private Instruction lowerUnaryMathIntrinsic(UnaryMathIntrinsicNode node) {
case TAN -> WasmImports.F64Tan;
case TANH -> WasmImports.F64Tanh;
case EXP -> WasmImports.F64Exp;
+ case CBRT -> WasmImports.F64Cbrt;
};
return new Call(masm.idFactory.forFunctionImport(imported), lowerExpression(node.getValue()));
diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js
index 54f6020fdf90..51b697f45a24 100644
--- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js
+++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js
@@ -43,6 +43,7 @@ wasmImports.compat = {
f64tanh: Math.tanh,
f64exp: Math.exp,
f64pow: Math.pow,
+ f64cbrt: Math.cbrt,
f32rem: (x, y) => x % y,
};