1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.replacements.test;
24
25import org.junit.Test;
26
27import org.graalvm.compiler.api.directives.GraalDirectives;
28import org.graalvm.compiler.api.replacements.ClassSubstitution;
29import org.graalvm.compiler.api.replacements.Fold;
30import org.graalvm.compiler.api.replacements.MethodSubstitution;
31import org.graalvm.compiler.bytecode.BytecodeProvider;
32import org.graalvm.compiler.core.test.GraalCompilerTest;
33import org.graalvm.compiler.nodes.ReturnNode;
34import org.graalvm.compiler.nodes.StartNode;
35import org.graalvm.compiler.nodes.StructuredGraph;
36import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
37import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
38import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
39import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
40import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory.InjectionProvider;
41import org.graalvm.compiler.replacements.NodeIntrinsificationProvider;
42
43public class FoldTest extends GraalCompilerTest {
44
45    private static class TestMethod {
46
47        public static int test() {
48            return 42;
49        }
50    }
51
52    static class FoldUtils {
53
54        private int number;
55
56        FoldUtils(int number) {
57            this.number = number;
58        }
59
60        @Fold
61        static int multiply(int a, int b) {
62            // we want to test whether @Fold works, so prevent automatic constant folding
63            return a * GraalDirectives.opaque(b);
64        }
65
66        @Fold
67        int getNumber() {
68            // we want to test whether @Fold works, so prevent automatic constant folding
69            return GraalDirectives.opaque(number);
70        }
71    }
72
73    @ClassSubstitution(TestMethod.class)
74    private static class TestMethodSubstitution {
75
76        private static final FoldUtils utils = new FoldUtils(21);
77
78        @MethodSubstitution
79        public static int test() {
80            return FoldUtils.multiply(utils.getNumber(), 2);
81        }
82    }
83
84    @Override
85    protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) {
86        InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins();
87        BytecodeProvider replacementBytecodeProvider = getReplacements().getReplacementBytecodeProvider();
88        Registration r = new Registration(invocationPlugins, TestMethod.class, replacementBytecodeProvider);
89        r.registerMethodSubstitution(TestMethodSubstitution.class, "test");
90        return super.editGraphBuilderConfiguration(conf);
91    }
92
93    public static int callTest() {
94        return TestMethod.test();
95    }
96
97    @Override
98    protected Plugins getDefaultGraphBuilderPlugins() {
99        Plugins ret = super.getDefaultGraphBuilderPlugins();
100        // manually register generated factories, jvmci service providers don't work from unit tests
101        InjectionProvider injection = new NodeIntrinsificationProvider(getMetaAccess(), getSnippetReflection(), getProviders().getForeignCalls(), null);
102        new PluginFactory_FoldTest().registerPlugins(ret.getInvocationPlugins(), injection);
103        return ret;
104    }
105
106    @Override
107    protected boolean checkHighTierGraph(StructuredGraph graph) {
108        // check that folding happened correctly
109        StartNode start = graph.start();
110        assert start.next() instanceof ReturnNode : "expected ReturnNode, got " + start.next();
111
112        ReturnNode ret = (ReturnNode) start.next();
113        assert ret.result().isConstant() : "expected ConstantNode, got " + ret.result();
114        return true;
115    }
116
117    @Test
118    public void snippetTest() {
119        test("callTest");
120    }
121}
122