1 /*
2 * Copyright (c) 2024, 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 */
23
24 import jdk.incubator.code.*;
25 import jdk.incubator.code.analysis.Inliner;
26 import jdk.incubator.code.dialect.core.CoreOp;
27 import jdk.incubator.code.dialect.java.JavaType;
28 import jdk.incubator.code.interpreter.Interpreter;
29 import org.junit.jupiter.api.Assertions;
30 import org.junit.jupiter.api.Test;
31
32 import java.lang.invoke.MethodHandles;
33 import java.util.List;
34
35 import static jdk.incubator.code.dialect.core.CoreOp.*;
36 import static jdk.incubator.code.dialect.core.CoreType.functionType;
37 import static jdk.incubator.code.dialect.java.JavaType.INT;
38
39 /*
40 * @test
41 * @modules jdk.incubator.code
42 * @run junit TestInline
43 */
44
45 public class TestInline {
46
47 @Test
48 public void testInline() {
49 Quoted q = (int a, int b) -> a + b;
50 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op();
51
52 // functional type = (int)int
53 CoreOp.FuncOp f = func("f", functionType(INT, INT))
54 .body(fblock -> {
55 Block.Parameter i = fblock.parameters().get(0);
56
57 Op.Result fortyTwo = fblock.op(constant(INT, 42));
58
59 var cb = Inliner.inline(fblock, cop, List.of(i, fortyTwo), Inliner.INLINE_RETURN);
60 Assertions.assertEquals(cb, fblock);
61 });
62
63 System.out.println(f.toText());
64
65 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1);
66 Assertions.assertEquals(43, ir);
67 }
68
69 @Test
70 public void testInlineVar() {
71 Quoted q = (int a, int b) -> a + b;
72 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op();
73
74 // functional type = (int)int
75 CoreOp.FuncOp f = func("f", functionType(INT, INT))
76 .body(fblock -> {
77 Block.Parameter i = fblock.parameters().get(0);
78
79 Op.Result fortyTwo = fblock.op(constant(INT, 42));
80
81 Op.Result v = fblock.op(var(fblock.op(constant(INT, 0))));
82
83 var cb = Inliner.inline(fblock, cop, List.of(i, fortyTwo), (b, value) -> {
84 b.op(varStore(v, value));
85 });
86 Assertions.assertEquals(cb, fblock);
87
88 fblock.op(return_(fblock.op(varLoad(v))));
89 });
90
91 System.out.println(f.toText());
92
93 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1);
94 Assertions.assertEquals(43, ir);
95 }
96
97
98 @Test
99 public void testInlineLowerMultipleReturn() {
100 Quoted q = (int a, int b) -> {
101 if (a < 10) {
102 return a + b;
103 }
104 return a - b;
105 };
106 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op();
107 System.out.println(cop.toText());
108 CoreOp.ClosureOp lcop = cop.transform(CopyContext.create(), OpTransformer.LOWERING_TRANSFORMER);
109 System.out.println(lcop.toText());
110
111 // functional type = (int)int
112 CoreOp.FuncOp f = func("f", functionType(INT, INT))
113 .body(fblock -> {
114 Block.Parameter i = fblock.parameters().get(0);
115
116 Op.Result fortyTwo = fblock.op(constant(INT, 42));
117
118 var cb = Inliner.inline(fblock, lcop, List.of(i, fortyTwo), Inliner.INLINE_RETURN);
119 Assertions.assertNotEquals(fblock, cb);
120 });
121 System.out.println(f.toText());
122
123 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1);
124 Assertions.assertEquals(43, ir);
125 }
126
127 @Test
128 public void testInlineLowerMultipleReturnVar() {
129 Quoted q = (int a, int b) -> {
130 if (a < 10) {
131 return a + b;
132 }
133 return a - b;
134 };
135 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op();
136 System.out.println(cop.toText());
137 CoreOp.ClosureOp lcop = cop.transform(CopyContext.create(), OpTransformer.LOWERING_TRANSFORMER);
138 System.out.println(lcop.toText());
139
140 // functional type = (int)int
141 CoreOp.FuncOp f = func("f", functionType(INT, INT))
142 .body(fblock -> {
143 Block.Parameter i = fblock.parameters().get(0);
144
145 Op.Result fortyTwo = fblock.op(constant(INT, 42));
146
147 Op.Result v = fblock.op(var(fblock.op(constant(INT, 0))));
148
149 var cb = Inliner.inline(fblock, lcop, List.of(i, fortyTwo), (b, value) -> {
150 b.op(varStore(v, value));
151 });
152 Assertions.assertNotEquals(fblock, cb);
153
154 cb.op(return_(cb.op(varLoad(v))));
155 });
156 System.out.println(f.toText());
157
158 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1);
159 Assertions.assertEquals(43, ir);
160 }
161
162 @Test
163 public void testInlineMultipleReturnLower() {
164 Quoted q = (int a, int b) -> {
165 if (a < 10) {
166 return a + b;
167 }
168 return a - b;
169 };
170 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op();
171 System.out.println(cop.toText());
172
173 CoreOp.FuncOp f = func("f", functionType(INT, INT))
174 .body(fblock -> {
175 Block.Parameter i = fblock.parameters().get(0);
176
177 Op.Result fortyTwo = fblock.op(constant(INT, 42));
178
179 var cb = Inliner.inline(fblock, cop, List.of(i, fortyTwo), Inliner.INLINE_RETURN);
180 Assertions.assertEquals(cb, fblock);
181 });
182 System.out.println(f.toText());
183
184 f = f.transform(OpTransformer.LOWERING_TRANSFORMER);
185 System.out.println(f.toText());
186
187 int ir = (int) Interpreter.invoke(MethodHandles.lookup(), f, 1);
188 Assertions.assertEquals(43, ir);
189 }
190
191 @Test
192 public void testInlineVoid() {
193 Quoted q = (int[] a) -> {
194 a[0] = 42;
195 return;
196 };
197 CoreOp.ClosureOp cop = (CoreOp.ClosureOp) q.op();
198
199 // functional type = (int)int
200 CoreOp.FuncOp f = func("f", functionType(JavaType.VOID, JavaType.type(int[].class)))
201 .body(fblock -> {
202 Block.Parameter a = fblock.parameters().get(0);
203
204 var cb = Inliner.inline(fblock, cop, List.of(a), Inliner.INLINE_RETURN);
205 Assertions.assertEquals(cb, fblock);
206 });
207
208 System.out.println(f.toText());
209
210 int[] a = new int[1];
211 Interpreter.invoke(MethodHandles.lookup(), f, a);
212 Assertions.assertEquals(42, a[0]);
213 }
214
215 }