mirror of
https://github.com/openjdk/jdk.git
synced 2026-06-06 18:53:37 +00:00
199 lines
6.5 KiB
Java
199 lines
6.5 KiB
Java
/*
|
|
* Copyright (c) 2026, 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.
|
|
*/
|
|
package compiler.c2.gvn;
|
|
|
|
import compiler.lib.ir_framework.*;
|
|
import jdk.internal.misc.Unsafe;
|
|
import jdk.test.lib.Asserts;
|
|
|
|
/*
|
|
* @test
|
|
* @bug 8376220
|
|
* @summary Tests that memory accesses can be elided when the compiler can see the value at the
|
|
* accessed memory location by walking the memory graph.
|
|
* @modules java.base/jdk.internal.misc
|
|
* @library /test/lib /
|
|
* @run driver ${test.main.class}
|
|
*/
|
|
public class TestFindStore {
|
|
private static final Unsafe U = Unsafe.getUnsafe();
|
|
|
|
static class P {
|
|
int v;
|
|
int u;
|
|
}
|
|
|
|
static final long V_OFFSET = U.objectFieldOffset(P.class, "v");
|
|
static final long U_OFFSET = U.objectFieldOffset(P.class, "u");
|
|
|
|
static class C1 extends P {}
|
|
static class C2 extends P {}
|
|
|
|
public static void main(String[] args) {
|
|
TestFramework.runWithFlags("--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED");
|
|
}
|
|
|
|
@Run(test = {"testLoad", "testStore", "testLoadDependent1", "testLoadDependent2", "testLoadArray",
|
|
"testLoadArrayOverlap", "testLoadIndependentAliasClasses", "testLoadMismatched",
|
|
"testLoadArrayCopy", "testLoadArrayCopyUnknownLength",
|
|
"testAllocationIndependence1", "testAllocationIndependence2"})
|
|
public void run() {
|
|
C1 c1 = new C1();
|
|
C2 c2 = new C2();
|
|
int[] a1 = new int[1000];
|
|
int[] a2 = new int[1000];
|
|
|
|
Asserts.assertEQ(0, testLoad(c1, c2, 0, 1));
|
|
Asserts.assertEQ(0, testStore(c2, 0).v);
|
|
Asserts.assertEQ(0, testLoadDependent1(c1, c1, 0, 1));
|
|
Asserts.assertEQ(1, testLoadDependent1(c2, c1, 0, 1));
|
|
Asserts.assertEQ(1, testLoadDependent2(c1, c1, 0, 1));
|
|
Asserts.assertEQ(0, testLoadDependent2(c2, c1, 0, 1));
|
|
|
|
Asserts.assertEQ(0, testLoadArray(a1, a2, 0, 1));
|
|
Asserts.assertEQ(0, testLoadArrayOverlap(a1, a2, 2, 0, 1));
|
|
Asserts.assertEQ(0, testLoadArrayOverlap(a1, a1, 0, 0, 1));
|
|
Asserts.assertEQ(1, testLoadArrayOverlap(a1, a1, 2, 0, 1));
|
|
Asserts.assertEQ(0, testLoadIndependentAliasClasses(c1, 0, 1));
|
|
Asserts.assertNE(0, testLoadMismatched(c1, 0, -1));
|
|
Asserts.assertEQ(1, testLoadArrayCopy(a1, a2, 1));
|
|
|
|
a1[2] = 0;
|
|
Asserts.assertEQ(1, testLoadArrayCopyUnknownLength(a1, a2, 100, 1));
|
|
a1[2] = 0;
|
|
Asserts.assertEQ(0, testLoadArrayCopyUnknownLength(a1, a2, 2, 1));
|
|
|
|
Asserts.assertEQ(3, testAllocationIndependence1(c1, 1, 2).v);
|
|
Asserts.assertEQ(3, testAllocationIndependence2(c1, 1, 2).v);
|
|
}
|
|
|
|
@Test
|
|
@IR(failOn = IRNode.LOAD)
|
|
static int testLoad(C1 c1, C2 c2, int v1, int v2) {
|
|
// c1 and c2 are provably independent
|
|
c1.v = v1;
|
|
c2.v = v2;
|
|
return c1.v;
|
|
}
|
|
|
|
@Test
|
|
@IR(counts = {IRNode.STORE, "1"}, phase = CompilePhase.BEFORE_MACRO_EXPANSION)
|
|
static C1 testStore(C2 c2, int v2) {
|
|
C1 c1 = new C1();
|
|
c2.v = v2;
|
|
c1.v = 0;
|
|
return c1;
|
|
}
|
|
|
|
@Test
|
|
@IR(counts = {IRNode.LOAD, "1"})
|
|
static int testLoadDependent1(P p, C1 c1, int v, int v1) {
|
|
// It cannot be proved that p and c1 are independent
|
|
c1.v = v1;
|
|
p.v = v;
|
|
return c1.v;
|
|
}
|
|
|
|
@Test
|
|
@IR(counts = {IRNode.LOAD, "1"})
|
|
static int testLoadDependent2(P p, C1 c1, int v, int v1) {
|
|
// It cannot be proved that p and c1 are independent
|
|
p.v = v;
|
|
c1.v = v1;
|
|
return p.v;
|
|
}
|
|
|
|
@Test
|
|
@IR(failOn = IRNode.LOAD)
|
|
static int testLoadArray(int[] a1, int[] a2, int v1, int v2) {
|
|
// a1[2] and a2[1] are provably independent
|
|
a1[2] = v1;
|
|
a2[1] = v2;
|
|
return a1[2];
|
|
}
|
|
|
|
@Test
|
|
@IR(counts = {IRNode.LOAD, "1"})
|
|
static int testLoadArrayOverlap(int[] a1, int[] a2, int idx, int v1, int v2) {
|
|
// Cannot prove that a1[2] and a2[idx] are independent
|
|
a1[2] = v1;
|
|
a2[idx] = v2;
|
|
return a1[2];
|
|
}
|
|
|
|
@Test
|
|
@IR(failOn = IRNode.LOAD)
|
|
static int testLoadIndependentAliasClasses(P p, int v, int u) {
|
|
p.v = v;
|
|
p.u = u;
|
|
return p.v;
|
|
}
|
|
|
|
@Test
|
|
@IR(counts = {IRNode.LOAD, "1"})
|
|
static int testLoadMismatched(P p, int v1, int v2) {
|
|
p.v = v1;
|
|
U.putIntUnaligned(p, (V_OFFSET + U_OFFSET) / 2, v2);
|
|
return p.v;
|
|
}
|
|
|
|
@Test
|
|
@IR(failOn = IRNode.LOAD, applyIf = {"ArrayCopyLoadStoreMaxElem", "<100"})
|
|
static int testLoadArrayCopy(int[] a1, int[] a2, int v) {
|
|
a2[2] = v;
|
|
// Should be large so the compiler does not just transform it into a couple of loads and stores
|
|
System.arraycopy(a2, 0, a1, 0, 100);
|
|
return a1[2];
|
|
}
|
|
|
|
@Test
|
|
@IR(counts = {IRNode.LOAD, "1"})
|
|
static int testLoadArrayCopyUnknownLength(int[] a1, int[] a2, int len, int v) {
|
|
a2[2] = v;
|
|
// Cannot determine if this overwrites a1[2]
|
|
System.arraycopy(a2, 0, a1, 0, len);
|
|
return a1[2];
|
|
}
|
|
|
|
@Test
|
|
@IR(failOn = IRNode.LOAD, phase = CompilePhase.BEFORE_MACRO_EXPANSION)
|
|
static C1 testAllocationIndependence1(C1 o1, int v1, int v2) {
|
|
// o1 and o2 are independent
|
|
o1.v = v1;
|
|
C1 o2 = new C1();
|
|
o2.v = o1.v + v2;
|
|
return o2;
|
|
}
|
|
|
|
@Test
|
|
@IR(failOn = IRNode.LOAD, phase = CompilePhase.BEFORE_MACRO_EXPANSION)
|
|
static C1 testAllocationIndependence2(C1 o1, int v1, int v2) {
|
|
// o1 and o2 are independent, but we also want CastPP(o1) and o2 being independent
|
|
C1 o2 = new C1();
|
|
o1.v = v1;
|
|
o2.v = v2;
|
|
o2.v = o1.v + o2.v;
|
|
return o2;
|
|
}
|
|
}
|