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