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