001/*
002 * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.compiler.test;
024
025import com.oracle.graal.debug.*;
026import com.oracle.graal.debug.Debug.*;
027import jdk.internal.jvmci.meta.*;
028
029import org.junit.*;
030
031import com.oracle.graal.nodes.*;
032import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
033import com.oracle.graal.nodes.calc.*;
034import com.oracle.graal.nodes.memory.*;
035import com.oracle.graal.nodes.memory.address.*;
036import com.oracle.graal.nodes.spi.*;
037import com.oracle.graal.nodes.type.*;
038import com.oracle.graal.phases.common.*;
039import com.oracle.graal.phases.tiers.*;
040
041public class PushNodesThroughPiTest extends GraalCompilerTest {
042
043    public static class A {
044
045        public long x = 20;
046    }
047
048    public static class B extends A {
049
050        public long y = 10;
051    }
052
053    public static class C extends B {
054
055        public long z = 5;
056    }
057
058    public static long test1Snippet(A a) {
059        C c = (C) a;
060        long ret = c.x; // this can be pushed before the checkcast
061        ret += c.y; // not allowed to push
062        ret += c.z; // not allowed to push
063        // the null-check should be canonicalized with the null-check of the checkcast
064        ret += c != null ? 100 : 200;
065        return ret;
066    }
067
068    @Test
069    public void test1() {
070        final String snippet = "test1Snippet";
071        try (Scope s = Debug.scope("PushThroughPi", new DebugDumpScope(snippet))) {
072            StructuredGraph graph = compileTestSnippet(snippet);
073            for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) {
074                OffsetAddressNode address = (OffsetAddressNode) rn.getAddress();
075                long disp = address.getOffset().asJavaConstant().asLong();
076
077                ResolvedJavaType receiverType = StampTool.typeOrNull(address.getBase());
078                ResolvedJavaField field = receiverType.findInstanceFieldWithOffset(disp, rn.getKind());
079
080                assert field != null : "Node " + rn + " tries to access a field which doesn't exists for this type";
081                if (field.getName().equals("x")) {
082                    Assert.assertTrue(address.getBase() instanceof ParameterNode);
083                } else {
084                    Assert.assertTrue(address.getBase().toString(), address.getBase() instanceof PiNode);
085                }
086            }
087
088            Assert.assertTrue(graph.getNodes().filter(IsNullNode.class).count() == 1);
089        } catch (Throwable e) {
090            throw Debug.handle(e);
091        }
092    }
093
094    private StructuredGraph compileTestSnippet(final String snippet) {
095        StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
096        PhaseContext context = new PhaseContext(getProviders());
097        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
098        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
099        canonicalizer.apply(graph, context);
100        new PushThroughPiPhase().apply(graph);
101        canonicalizer.apply(graph, context);
102
103        return graph;
104    }
105}