forked from oracle/graal
-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #696 from zakkak/2024-03-13-backports-21-sync
2024-03-13 backports 21 sync
- Loading branch information
Showing
246 changed files
with
4,509 additions
and
2,519 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
...ler.test/src/org/graalvm/compiler/core/test/ConditionalEliminationStampInversionTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
* Copyright (c) 2023, 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 org.graalvm.compiler.core.test; | ||
|
||
import org.graalvm.compiler.nodes.ConstantNode; | ||
import org.graalvm.compiler.nodes.FixedGuardNode; | ||
import org.graalvm.compiler.nodes.IfNode; | ||
import org.graalvm.compiler.nodes.LogicNode; | ||
import org.graalvm.compiler.nodes.NodeView; | ||
import org.graalvm.compiler.nodes.StructuredGraph; | ||
import org.graalvm.compiler.nodes.ValueNode; | ||
import org.graalvm.compiler.nodes.calc.AndNode; | ||
import org.graalvm.compiler.nodes.calc.IntegerEqualsNode; | ||
import org.graalvm.compiler.nodes.calc.IntegerTestNode; | ||
import org.graalvm.compiler.nodes.calc.SignExtendNode; | ||
import org.graalvm.compiler.nodes.util.GraphUtil; | ||
import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; | ||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; | ||
import org.junit.Test; | ||
|
||
import jdk.vm.ci.code.InvalidInstalledCodeException; | ||
import jdk.vm.ci.meta.DeoptimizationAction; | ||
import jdk.vm.ci.meta.DeoptimizationReason; | ||
|
||
/** | ||
* Tests the correctness of conditional elimination when inverting stamps along | ||
* {@link SignExtendNode}. The test artificially creates a graph whith the optimizable pattern: | ||
* {@code ((val & CONST) == CONST)}, which provides information about the set bits in val, if the | ||
* condition is used in a guard which is assumed to hold. The partial information about bits which | ||
* are set in {@code x} are propagated "upwards". A {@link SignExtendNode} must treat the partial | ||
* information correctly with respect to the extension bits and handle contradictions. | ||
* </p> | ||
* If {@code CONST = 1 << 4 = 0001 0000} and we assume the condition holds, we can refine a stamp | ||
* {@code xxxx xx11} for {@code val} to {@code xxx1 xx11}. Inverting this refined stamp along an | ||
* artificial 4->8 bit sign extension should treat the extension as {@code 1111} and produce an | ||
* inverted stamp of {@code xx11} or, even better {@code 1x11}, because we know the MSB has to be | ||
* one from the extension. | ||
* </p> | ||
* If the inversion is performed incorrectly, the inner condition could be considered as always | ||
* false and removing it during conditional elimination. | ||
*/ | ||
public class ConditionalEliminationStampInversionTest extends GraalCompilerTest { | ||
|
||
public static boolean snippet(byte b) { | ||
short s = b; | ||
int i = s; | ||
|
||
if ((i & (1 << 16)) == (1 << 16)) { | ||
if (s == -5) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
@Test | ||
public void test() throws InvalidInstalledCodeException { | ||
StructuredGraph g = parseEager("snippet", AllowAssumptions.YES); | ||
|
||
// replace the IntegerTest by an equivalent and/== pattern | ||
ValueNode intTest = g.getNodes().filter(IntegerTestNode.class).first(); | ||
assertTrue("IntegerTestNode expected in graph.", intTest != null); | ||
|
||
ValueNode signExtend = g.getNodes().filter(SignExtendNode.class).first(); | ||
assertTrue("SignExtendNode expected in graph.", signExtend != null); | ||
|
||
ValueNode and = g.addOrUnique(AndNode.create(signExtend, ConstantNode.forInt(1 << 16, g), NodeView.DEFAULT)); | ||
and.inferStamp(); | ||
LogicNode intEq = g.addOrUnique(IntegerEqualsNode.create(and, ConstantNode.forInt(1 << 16, g), NodeView.DEFAULT)); | ||
intEq.inferStamp(); | ||
|
||
intTest.replaceAtUsages(intEq); | ||
|
||
// replace the if by a fixed guard to trigger conditional elimination for the and/== pattern | ||
ValueNode ifNode = (ValueNode) intEq.usages().first(); | ||
assertTrue("IfNode expected as first usage of IntegerEqualsNode.", ifNode != null && ifNode instanceof IfNode); | ||
|
||
FixedGuardNode guard = g.add(new FixedGuardNode(intEq, DeoptimizationReason.ArithmeticException, DeoptimizationAction.InvalidateRecompile)); | ||
GraphUtil.killCFG(((IfNode) ifNode).trueSuccessor()); | ||
g.replaceSplitWithFixed((IfNode) ifNode, guard, ((IfNode) ifNode).falseSuccessor()); | ||
|
||
new ConditionalEliminationPhase(false).apply(g, getDefaultHighTierContext()); | ||
|
||
// the inner condition should still be alive and the following execution return true | ||
assert (boolean) getCode(getResolvedJavaMethod("snippet"), g, true, true, getInitialOptions()).executeVarargs((byte) -5); | ||
} | ||
} |
134 changes: 134 additions & 0 deletions
134
...m.compiler.test/src/org/graalvm/compiler/hotspot/amd64/test/ReadEliminateLowTierTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/* | ||
* Copyright (c) 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 | ||
* 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 org.graalvm.compiler.hotspot.amd64.test; | ||
|
||
import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; | ||
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; | ||
|
||
import org.junit.Test; | ||
import org.graalvm.compiler.api.directives.GraalDirectives; | ||
import org.graalvm.compiler.core.common.type.StampFactory; | ||
import org.graalvm.compiler.core.test.GraalCompilerTest; | ||
import org.graalvm.compiler.graph.Node; | ||
import org.graalvm.compiler.graph.NodeClass; | ||
import org.graalvm.compiler.nodeinfo.InputType; | ||
import org.graalvm.compiler.nodeinfo.NodeInfo; | ||
import org.graalvm.compiler.nodes.FixedWithNextNode; | ||
import org.graalvm.compiler.nodes.ValueNode; | ||
import org.graalvm.compiler.nodes.calc.IsNullNode; | ||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; | ||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; | ||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; | ||
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; | ||
import org.graalvm.compiler.nodes.memory.ReadNode; | ||
import org.graalvm.compiler.nodes.spi.Canonicalizable; | ||
import org.graalvm.compiler.nodes.spi.CanonicalizerTool; | ||
import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase; | ||
|
||
import jdk.vm.ci.code.InstalledCode; | ||
import jdk.vm.ci.code.InvalidInstalledCodeException; | ||
import jdk.vm.ci.meta.ResolvedJavaMethod; | ||
|
||
/** | ||
* Test to ensure that late elimination of memory reads preserves necessary null check semantic with | ||
* respect to {@link UseTrappingNullChecksPhase}. | ||
*/ | ||
public class ReadEliminateLowTierTest extends GraalCompilerTest { | ||
static class T { | ||
int x; | ||
int y; | ||
int z; | ||
} | ||
|
||
public static int trappingSnippet(T t) { | ||
if (t == null) { | ||
GraalDirectives.deoptimizeAndInvalidate(); | ||
return -1; | ||
} | ||
/* | ||
* The first read from t here will act as trapping null check for all the others. We must | ||
* not remove this read if its used as a null check even if it does not have any usages any | ||
* more. | ||
*/ | ||
foldAfterTrappingNullChecks(t.x); | ||
int result = t.y + t.z; | ||
return result; | ||
} | ||
|
||
static void foldAfterTrappingNullChecks(@SuppressWarnings("unused") int i) { | ||
} | ||
|
||
@Override | ||
protected Plugins getDefaultGraphBuilderPlugins() { | ||
Plugins p = super.getDefaultGraphBuilderPlugins(); | ||
Registration r = new Registration(p.getInvocationPlugins(), ReadEliminateLowTierTest.class); | ||
r.register(new InvocationPlugin("foldAfterTrappingNullChecks", int.class) { | ||
@Override | ||
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { | ||
b.append(new FixedUsageUntilFinalCanon(arg)); | ||
return true; | ||
} | ||
}); | ||
return p; | ||
} | ||
|
||
/** | ||
* Node that gets optimized away be late canonicalization. | ||
*/ | ||
@NodeInfo(cycles = CYCLES_0, size = SIZE_0, allowedUsageTypes = {InputType.Anchor}) | ||
public static class FixedUsageUntilFinalCanon extends FixedWithNextNode implements Canonicalizable { | ||
public static final NodeClass<FixedUsageUntilFinalCanon> TYPE = NodeClass.create(FixedUsageUntilFinalCanon.class); | ||
|
||
@OptionalInput ValueNode object; | ||
|
||
public FixedUsageUntilFinalCanon(ValueNode object) { | ||
super(TYPE, StampFactory.forVoid()); | ||
this.object = object; | ||
} | ||
|
||
@Override | ||
public Node canonical(CanonicalizerTool tool) { | ||
// after trapping nulls | ||
if (graph().getNodes().filter(IsNullNode.class).count() == 0) { | ||
if (tool.allUsagesAvailable() && object instanceof ReadNode) { | ||
ReadNode r = (ReadNode) object; | ||
if (r.hasExactlyOneUsage() && r.usages().first().equals(this)) { | ||
return null; | ||
} | ||
} | ||
} | ||
return this; | ||
} | ||
} | ||
|
||
@Test | ||
public void test() throws InvalidInstalledCodeException { | ||
InstalledCode ic = getCode(getResolvedJavaMethod("trappingSnippet")); | ||
assert lastCompiledGraph != null; | ||
ic.executeVarargs(new T()); | ||
ic.executeVarargs((Object) null); | ||
} | ||
|
||
} |
Oops, something went wrong.