From 7d11401a5cdcea13795916a5e8e53a9a79d5e36d Mon Sep 17 00:00:00 2001 From: mspasic Date: Wed, 30 Oct 2024 13:50:15 +0100 Subject: [PATCH 1/3] [GR-47080] Add support for side effect free LogicCompareAndSwap. --- .../amd64/AMD64HotSpotLIRGenerator.java | 1 - .../java/AbstractCompareAndSwapNode.java | 11 ++++++++++- .../nodes/java/LogicCompareAndSwapNode.java | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index 74fa7dbaa13a..58ef9e1682fa 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -75,7 +75,6 @@ import jdk.graal.compiler.lir.amd64.AMD64Move; import jdk.graal.compiler.lir.amd64.AMD64Move.MoveFromRegOp; import jdk.graal.compiler.lir.amd64.AMD64PrefetchOp; -import jdk.graal.compiler.lir.amd64.AMD64ReadTimestampCounterWithProcid; import jdk.graal.compiler.lir.amd64.AMD64RestoreRegistersOp; import jdk.graal.compiler.lir.amd64.AMD64SaveRegistersOp; import jdk.graal.compiler.lir.amd64.AMD64VZeroUpper; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java index 100bbef9441a..1b567dac64ec 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/AbstractCompareAndSwapNode.java @@ -57,6 +57,8 @@ public abstract class AbstractCompareAndSwapNode extends FixedAccessNode impleme @OptionalInput(State) FrameState stateAfter; protected final MemoryOrderMode memoryOrder; + private final boolean hasSideEffect; + @Override public FrameState stateAfter() { return stateAfter; @@ -71,7 +73,7 @@ public void setStateAfter(FrameState x) { @Override public boolean hasSideEffect() { - return true; + return hasSideEffect; } public ValueNode getExpectedValue() { @@ -89,11 +91,18 @@ public final MemoryOrderMode getMemoryOrder() { public AbstractCompareAndSwapNode(NodeClass c, AddressNode address, LocationIdentity location, ValueNode expectedValue, ValueNode newValue, BarrierType barrierType, Stamp stamp, MemoryOrderMode memoryOrder) { + this(c, address, location, expectedValue, newValue, barrierType, stamp, memoryOrder, true); + + } + + protected AbstractCompareAndSwapNode(NodeClass c, AddressNode address, LocationIdentity location, ValueNode expectedValue, ValueNode newValue, + BarrierType barrierType, Stamp stamp, MemoryOrderMode memoryOrder, boolean hasSideEffect) { super(c, address, location, stamp, barrierType); assert expectedValue.getStackKind() == newValue.getStackKind() : Assertions.errorMessageContext("c", c, "adr", address, "loc", location, "expected", expectedValue, "newVal", newValue); this.expectedValue = expectedValue; this.newValue = newValue; this.memoryOrder = memoryOrder; + this.hasSideEffect = hasSideEffect; } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java index 4022c488c1f3..6a528a377885 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java @@ -27,6 +27,7 @@ import static jdk.graal.compiler.nodeinfo.NodeCycles.CYCLES_8; import static jdk.graal.compiler.nodeinfo.NodeSize.SIZE_8; +import jdk.graal.compiler.nodes.FrameState; import org.graalvm.word.LocationIdentity; import jdk.graal.compiler.core.common.LIRKind; @@ -54,7 +55,12 @@ public final class LogicCompareAndSwapNode extends AbstractCompareAndSwapNode { public static final NodeClass TYPE = NodeClass.create(LogicCompareAndSwapNode.class); public LogicCompareAndSwapNode(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, BarrierType barrierType, MemoryOrderMode memoryOrder) { - super(TYPE, address, location, expectedValue, newValue, barrierType, StampFactory.forInteger(JavaKind.Int, 0, 1), memoryOrder); + this(address, expectedValue, newValue, location, barrierType, memoryOrder, true); + } + + private LogicCompareAndSwapNode(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, BarrierType barrierType, MemoryOrderMode memoryOrder, + boolean hasSideEffect) { + super(TYPE, address, location, expectedValue, newValue, barrierType, StampFactory.forInteger(JavaKind.Int, 0, 1), memoryOrder, hasSideEffect); } @Override @@ -70,4 +76,15 @@ public void generate(NodeLIRBuilderTool gen) { gen.setResult(this, result); } + + /** + * This is a special form of {@link LogicCompareAndSwapNode} that does not have a side effect to + * the interpreter, i.e., it does not modify memory that is visible to other threads or modifies + * state beyond what is captured in {@link FrameState} nodes. Thus, it should only be used with + * caution in suitable scenarios. + */ + public static LogicCompareAndSwapNode createWithoutSideEffect(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location) { + return new LogicCompareAndSwapNode(address, expectedValue, newValue, location, BarrierType.NONE, MemoryOrderMode.VOLATILE, false); + } + } From e0c7a8ec3be4ab158daae1b5aaaa79493c821d38 Mon Sep 17 00:00:00 2001 From: mspasic Date: Wed, 30 Oct 2024 15:13:28 +0100 Subject: [PATCH 2/3] [GR-47080] Add support for TimeStampNode intrinsic. --- .../core/aarch64/AArch64LIRGenerator.java | 8 ++++++++ .../core/amd64/AMD64LIRGenerator.java | 19 +++++++++++++++++++ .../amd64/AMD64HotSpotLIRGenerator.java | 18 ------------------ .../aarch64/AArch64ReadTimestampCounter.java | 6 ++++++ .../nodes/java/LogicCompareAndSwapNode.java | 13 ++++++------- .../graal/amd64/SubstrateAMD64Backend.java | 2 +- 6 files changed, 40 insertions(+), 26 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java index 19c4d22cf3ec..ef4887be25f2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64LIRGenerator.java @@ -88,6 +88,7 @@ import jdk.graal.compiler.lir.aarch64.AArch64Move; import jdk.graal.compiler.lir.aarch64.AArch64Move.MembarOp; import jdk.graal.compiler.lir.aarch64.AArch64PauseOp; +import jdk.graal.compiler.lir.aarch64.AArch64ReadTimestampCounter; import jdk.graal.compiler.lir.aarch64.AArch64SHA1Op; import jdk.graal.compiler.lir.aarch64.AArch64SHA256Op; import jdk.graal.compiler.lir.aarch64.AArch64SHA3Op; @@ -383,6 +384,13 @@ public void emitCompareBranch(PlatformKind cmpKind, Value left, final Value righ append(new BranchOp(cmpCondition, trueDestination, falseDestination, trueDestinationProbability)); } + @Override + public Value emitTimeStamp() { + Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); + append(new AArch64ReadTimestampCounter(result)); + return result; + } + private static ConditionFlag toConditionFlag(boolean isInt, Condition cond, boolean unorderedIsTrue) { return isInt ? toIntConditionFlag(cond) : toFloatConditionFlag(cond, unorderedIsTrue); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java index 8ff803ce83a2..9a386039a530 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64LIRGenerator.java @@ -120,6 +120,7 @@ import jdk.graal.compiler.lir.amd64.AMD64Move.MembarOp; import jdk.graal.compiler.lir.amd64.AMD64Move.StackLeaOp; import jdk.graal.compiler.lir.amd64.AMD64PauseOp; +import jdk.graal.compiler.lir.amd64.AMD64ReadTimestampCounterWithProcid; import jdk.graal.compiler.lir.amd64.AMD64SHA1Op; import jdk.graal.compiler.lir.amd64.AMD64SHA256AVX2Op; import jdk.graal.compiler.lir.amd64.AMD64SHA256Op; @@ -1215,4 +1216,22 @@ public boolean useCountLeadingZerosInstruction() { public boolean useCountTrailingZerosInstruction() { return supportsCPUFeature(CPUFeature.BMI1); } + + @Override + public Value emitTimeStamp() { + AMD64ReadTimestampCounterWithProcid timestamp = new AMD64ReadTimestampCounterWithProcid(); + append(timestamp); + // Combine RDX and RAX into a single 64-bit register. + AllocatableValue lo = timestamp.getLowResult(); + Value hi = getArithmetic().emitZeroExtend(timestamp.getHighResult(), 32, 64); + return combineLoAndHi(lo, hi); + } + + /** + * Combines two 32 bit values to a 64 bit value: ( (hi << 32) | lo ). + */ + protected Value combineLoAndHi(Value lo, Value hi) { + Value shiftedHi = getArithmetic().emitShl(hi, emitConstant(LIRKind.value(AMD64Kind.DWORD), JavaConstant.forInt(32))); + return getArithmetic().emitOr(shiftedHi, lo); + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index 58ef9e1682fa..04414791e04b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -623,24 +623,6 @@ protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, Label return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp); } - @Override - public Value emitTimeStamp() { - AMD64ReadTimestampCounterWithProcid timestamp = new AMD64ReadTimestampCounterWithProcid(); - append(timestamp); - // Combine RDX and RAX into a single 64-bit register. - AllocatableValue lo = timestamp.getLowResult(); - Value hi = getArithmetic().emitZeroExtend(timestamp.getHighResult(), 32, 64); - return combineLoAndHi(lo, hi); - } - - /** - * Combines two 32 bit values to a 64 bit value: ( (hi << 32) | lo ). - */ - private Value combineLoAndHi(Value lo, Value hi) { - Value shiftedHi = getArithmetic().emitShl(hi, emitConstant(LIRKind.value(AMD64Kind.DWORD), JavaConstant.forInt(32))); - return getArithmetic().emitOr(shiftedHi, lo); - } - @Override public int getArrayLengthOffset() { return config.arrayOopDescLengthOffset(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java index 0a3786a0a194..131a0bf97b0b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64ReadTimestampCounter.java @@ -33,6 +33,7 @@ import jdk.graal.compiler.lir.LIRInstructionClass; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; /** * Reads the CNTVCT_EL0 generic timer register. Note that two reads to this system register from the @@ -48,8 +49,13 @@ public AArch64ReadTimestampCounter(AllocatableValue result) { this.result = result; } + public Value getResult() { + return result; + } + @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + masm.isb(); masm.mrs(asRegister(result), AArch64Assembler.SystemRegister.CNTVCT_EL0); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java index 6a528a377885..7b06707d3f41 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/LogicCompareAndSwapNode.java @@ -27,7 +27,6 @@ import static jdk.graal.compiler.nodeinfo.NodeCycles.CYCLES_8; import static jdk.graal.compiler.nodeinfo.NodeSize.SIZE_8; -import jdk.graal.compiler.nodes.FrameState; import org.graalvm.word.LocationIdentity; import jdk.graal.compiler.core.common.LIRKind; @@ -55,12 +54,12 @@ public final class LogicCompareAndSwapNode extends AbstractCompareAndSwapNode { public static final NodeClass TYPE = NodeClass.create(LogicCompareAndSwapNode.class); public LogicCompareAndSwapNode(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, BarrierType barrierType, MemoryOrderMode memoryOrder) { - this(address, expectedValue, newValue, location, barrierType, memoryOrder, true); + this(TYPE, address, expectedValue, newValue, location, barrierType, memoryOrder, true); } - private LogicCompareAndSwapNode(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, BarrierType barrierType, MemoryOrderMode memoryOrder, - boolean hasSideEffect) { - super(TYPE, address, location, expectedValue, newValue, barrierType, StampFactory.forInteger(JavaKind.Int, 0, 1), memoryOrder, hasSideEffect); + private LogicCompareAndSwapNode(NodeClass type, AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location, + BarrierType barrierType, MemoryOrderMode memoryOrder, boolean hasSideEffect) { + super(type, address, location, expectedValue, newValue, barrierType, StampFactory.forInteger(JavaKind.Int, 0, 1), memoryOrder, hasSideEffect); } @Override @@ -80,11 +79,11 @@ public void generate(NodeLIRBuilderTool gen) { /** * This is a special form of {@link LogicCompareAndSwapNode} that does not have a side effect to * the interpreter, i.e., it does not modify memory that is visible to other threads or modifies - * state beyond what is captured in {@link FrameState} nodes. Thus, it should only be used with + * state beyond what is captured in {@code FrameState} nodes. Thus, it should only be used with * caution in suitable scenarios. */ public static LogicCompareAndSwapNode createWithoutSideEffect(AddressNode address, ValueNode expectedValue, ValueNode newValue, LocationIdentity location) { - return new LogicCompareAndSwapNode(address, expectedValue, newValue, location, BarrierType.NONE, MemoryOrderMode.VOLATILE, false); + return new LogicCompareAndSwapNode(TYPE, address, expectedValue, newValue, location, BarrierType.NONE, MemoryOrderMode.PLAIN, false); } } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java index 7e330886f8f6..0ed747f3668b 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 From fcee29b4768a7a6bbfbf1488cb37c0c2c350e7f9 Mon Sep 17 00:00:00 2001 From: Bernhard Urban-Forster Date: Wed, 22 Jan 2025 15:31:17 +0100 Subject: [PATCH 3/3] [AArch64] Fix encoding for ENTVCT_EL0 --- .../src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java index 55633a24ab1e..bfec44fedb3d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java @@ -1069,7 +1069,7 @@ public enum SystemRegister { FPCR(0b11, 0b011, 0b0100, 0b0100, 0b000), FPSR(0b11, 0b011, 0b0100, 0b0100, 0b001), /* Counter-timer Virtual Count register */ - CNTVCT_EL0(0b11, 0b011, 0b110, 0b0000, 0b010); + CNTVCT_EL0(0b11, 0b011, 0b1110, 0b0000, 0b010); SystemRegister(int op0, int op1, int crn, int crm, int op2) { this.op0 = op0;