1 import jdk.incubator.code.*; 2 import jdk.incubator.code.analysis.SSA; 3 import jdk.incubator.code.interpreter.Interpreter; 4 import org.junit.jupiter.api.Assertions; 5 import org.junit.jupiter.api.Test; 6 7 import java.lang.invoke.MethodHandles; 8 import java.lang.reflect.Method; 9 import java.util.Optional; 10 import java.util.function.Predicate; 11 import java.util.stream.Stream; 12 13 import static jdk.incubator.code.dialect.core.CoreOp.FuncOp; 14 import static jdk.incubator.code.dialect.core.CoreOp.VarAccessOp.VarLoadOp; 15 import static jdk.incubator.code.dialect.core.CoreOp.VarAccessOp.VarStoreOp; 16 import static jdk.incubator.code.dialect.core.CoreOp.VarOp; 17 18 /* 19 * @test 20 * @modules jdk.incubator.code 21 * @run junit TestRemoveFinalVars 22 */ 23 24 public class TestRemoveFinalVars { 25 26 @CodeReflection 27 static boolean f() { 28 final int x = 8; // final var 29 int y = x + 2; // final var 30 int z = y + 3; // non final var 31 z++; 32 return x == 8 && y == 10 && z == 14; 33 } 34 35 @Test 36 void test() { 37 FuncOp f = getFuncOp(this.getClass(),"f"); 38 System.out.println(f.toText()); 39 FuncOp lf = lower(f); 40 System.out.println(lf.toText()); 41 42 FuncOp f2 = f.transform(TestRemoveFinalVars::rmFinalVars); 43 System.out.println(f2.toText()); 44 FuncOp lf2 = lower(f2); 45 System.out.println(lf2.toText()); 46 47 Assertions.assertEquals(Interpreter.invoke(MethodHandles.lookup(), lf2), Interpreter.invoke(MethodHandles.lookup(), lf)); 48 49 Op op = SSA.transform(lower(f)); 50 System.out.println(op.toText()); 51 } 52 53 static FuncOp lower(FuncOp funcOp) { 54 return funcOp.transform(OpTransformer.LOWERING_TRANSFORMER); 55 } 56 57 static Block.Builder rmFinalVars(Block.Builder block, Op op) { 58 if (op instanceof VarOp varOp) { 59 // Is the variable stored to? If not we can remove it 60 // otherwise, it's not considered final and we copy it 61 if (isValueUsedWithOp(varOp.result(), o -> o instanceof VarStoreOp)) { 62 block.op(varOp); 63 } 64 } else if (op instanceof VarLoadOp varLoadOp) { 65 // If the variable is not stored to 66 if (!isValueUsedWithOp(varLoadOp.varOp().result(), o -> o instanceof VarStoreOp)) { 67 // Map result of load from variable to the value that initialized the variable 68 // Subsequently encountered input operations using the result will be copied 69 // to output operations using the mapped value 70 CopyContext cc = block.context(); 71 cc.mapValue(varLoadOp.result(), cc.getValue(varLoadOp.varOp().operands().get(0))); 72 } else { 73 block.op(varLoadOp); 74 } 75 } else { 76 block.op(op); 77 } 78 return block; 79 } 80 81 private static boolean isValueUsedWithOp(Value value, Predicate<Op> opPredicate) { 82 for (Op.Result user : value.uses()) { 83 if (opPredicate.test(user.op())) { 84 return true; 85 } 86 } 87 return false; 88 } 89 90 static FuncOp getFuncOp(Class<?> c, String name) { 91 Optional<Method> om = Stream.of(c.getDeclaredMethods()) 92 .filter(m -> m.getName().equals(name)) 93 .findFirst(); 94 95 Method m = om.get(); 96 return Op.ofMethod(m).get(); 97 } 98 }