UnsafeReadEliminationTest.java revision 12651:6ef01bd40ce2
11590Srgrimes/*
2140392Srwatson * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
397377Sdes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41590Srgrimes *
597377Sdes * This code is free software; you can redistribute it and/or modify it
697377Sdes * under the terms of the GNU General Public License version 2 only, as
797377Sdes * published by the Free Software Foundation.
897377Sdes *
997377Sdes * This code is distributed in the hope that it will be useful, but WITHOUT
101590Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
111590Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
121590Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
131590Srgrimes * accompanied this code).
141590Srgrimes *
151590Srgrimes * You should have received a copy of the GNU General Public License version
161590Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
171590Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18140392Srwatson *
19140392Srwatson * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20140392Srwatson * or visit www.oracle.com if you need additional information or have any
21140392Srwatson * questions.
22140392Srwatson */
23140392Srwatsonpackage org.graalvm.compiler.core.test;
24140392Srwatson
25140392Srwatsonimport java.lang.reflect.Field;
26140392Srwatson
27140392Srwatsonimport org.junit.Assert;
28140392Srwatsonimport org.junit.Test;
29140392Srwatson
30140392Srwatsonimport org.graalvm.compiler.api.directives.GraalDirectives;
31140392Srwatsonimport org.graalvm.compiler.nodes.StructuredGraph;
32140392Srwatsonimport org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
33140392Srwatsonimport org.graalvm.compiler.nodes.extended.UnsafeAccessNode;
34140392Srwatsonimport org.graalvm.compiler.nodes.memory.ReadNode;
35140392Srwatsonimport org.graalvm.compiler.nodes.memory.WriteNode;
36140392Srwatsonimport org.graalvm.compiler.nodes.spi.LoweringTool;
37140392Srwatsonimport org.graalvm.compiler.phases.common.CanonicalizerPhase;
38140392Srwatsonimport org.graalvm.compiler.phases.common.LoweringPhase;
39140392Srwatsonimport org.graalvm.compiler.phases.tiers.PhaseContext;
40140392Srwatsonimport org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase;
41140392Srwatsonimport org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
42140392Srwatson
431590Srgrimesimport sun.misc.Unsafe;
441590Srgrimes
451590Srgrimespublic class UnsafeReadEliminationTest extends GraalCompilerTest {
461590Srgrimes
471590Srgrimes    public static final Unsafe UNSAFE;
481590Srgrimes    static {
491590Srgrimes        try {
501590Srgrimes            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
511590Srgrimes            theUnsafe.setAccessible(true);
521590Srgrimes            UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class);
531590Srgrimes        } catch (Exception e) {
541590Srgrimes            throw new RuntimeException("Exception while trying to get Unsafe", e);
551590Srgrimes        }
561590Srgrimes    }
571590Srgrimes
581590Srgrimes    public static long[] Memory = new long[]{1, 2};
591590Srgrimes    public static double SideEffectD;
601590Srgrimes    public static double SideEffectL;
6114440Smarkm
621590Srgrimes    public static long test1Snippet(double a) {
631590Srgrimes        final Object m = Memory;
641590Srgrimes        if (a > 0) {
651590Srgrimes            UNSAFE.putDouble(m, (long) Unsafe.ARRAY_LONG_BASE_OFFSET, a);
66127848Scharnier        } else {
671590Srgrimes            SideEffectL = UNSAFE.getLong(m, (long) Unsafe.ARRAY_LONG_BASE_OFFSET);
681590Srgrimes        }
69127848Scharnier        return UNSAFE.getLong(m, (long) Unsafe.ARRAY_LONG_BASE_OFFSET);
7028099Scharnier    }
711590Srgrimes
72127848Scharnier    public static class A {
73127848Scharnier        long[][] o;
74127848Scharnier        long[][] p;
751590Srgrimes    }
761590Srgrimes
771590Srgrimes    public static Object test2Snippet(A a, int c) {
7877220Smarkm        Object phi = null;
791590Srgrimes        if (c != 0) {
80161815Scsjp            long[][] r = a.o;
81161815Scsjp            phi = r;
82161815Scsjp            UNSAFE.putDouble(r, (long) Unsafe.ARRAY_LONG_BASE_OFFSET, 12d);
83161815Scsjp        } else {
84161815Scsjp            long[][] r = a.p;
851590Srgrimes            phi = r;
861590Srgrimes            UNSAFE.putLong(r, (long) Unsafe.ARRAY_LONG_BASE_OFFSET, 123);
87200462Sdelphij        }
8877220Smarkm        GraalDirectives.controlFlowAnchor();
891590Srgrimes        SideEffectD = UNSAFE.getDouble(phi, (long) Unsafe.ARRAY_LONG_BASE_OFFSET);
901590Srgrimes        return phi;
9177220Smarkm    }
921590Srgrimes
931590Srgrimes    @Test
941590Srgrimes    public void test01() {
951590Srgrimes        StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.NO);
961590Srgrimes        testEarlyReadElimination(graph, 3, 2);
97161815Scsjp    }
9821646Sdavidn
9974874Smarkm    @Test
10091745Sdes    public void test02() {
10174874Smarkm        StructuredGraph graph = parseEager("test1Snippet", AllowAssumptions.NO);
102113262Sdes        testPartialEscapeReadElimination(graph, 3, 2);
103113262Sdes    }
104113262Sdes
105113262Sdes    @Test
106113262Sdes    public void test03() {
107113262Sdes        StructuredGraph graph = parseEager("test2Snippet", AllowAssumptions.NO);
108113262Sdes        testEarlyReadElimination(graph, 3, 3);
109113262Sdes    }
110113262Sdes
111113262Sdes    @Test
112113262Sdes    public void test04() {
113113262Sdes        StructuredGraph graph = parseEager("test2Snippet", AllowAssumptions.NO);
114113262Sdes        testEarlyReadElimination(graph, 3, 3);
115113262Sdes    }
116113262Sdes
117113262Sdes    public void testEarlyReadElimination(StructuredGraph graph, int reads, int writes) {
118113262Sdes        PhaseContext context = getDefaultHighTierContext();
119113262Sdes        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
12077220Smarkm        canonicalizer.apply(graph, context);
12174874Smarkm        new EarlyReadEliminationPhase(canonicalizer).apply(graph, context);
12274874Smarkm        Assert.assertEquals(3, graph.getNodes().filter(UnsafeAccessNode.class).count());
123113262Sdes        // after lowering the same applies for reads and writes
124113262Sdes        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
125113262Sdes        canonicalizer.apply(graph, context);
126113262Sdes        new EarlyReadEliminationPhase(canonicalizer).apply(graph, context);
127113262Sdes        Assert.assertEquals(reads, graph.getNodes().filter(ReadNode.class).count());
128113262Sdes        Assert.assertEquals(writes, graph.getNodes().filter(WriteNode.class).count());
129113262Sdes    }
130113262Sdes
131130409Smarkm    public void testPartialEscapeReadElimination(StructuredGraph graph, int reads, int writes) {
132113262Sdes        PhaseContext context = getDefaultHighTierContext();
13377220Smarkm        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
1343702Spst        canonicalizer.apply(graph, context);
13577220Smarkm        new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context);
1361590Srgrimes        Assert.assertEquals(3, graph.getNodes().filter(UnsafeAccessNode.class).count());
13777220Smarkm        // after lowering the same applies for reads and writes
13877220Smarkm        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
13977220Smarkm        canonicalizer.apply(graph, context);
14077220Smarkm        new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context);
141130409Smarkm        Assert.assertEquals(reads, graph.getNodes().filter(ReadNode.class).count());
142130409Smarkm        Assert.assertEquals(writes, graph.getNodes().filter(WriteNode.class).count());
143130409Smarkm    }
14477220Smarkm
14577220Smarkm}
14677220Smarkm