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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package experiments;
27
28
29 import optkl.codebuilders.JavaCodeBuilder;
30 import optkl.Trxfmr;
31 import static optkl.OpHelper.Invoke;
32 import static optkl.OpHelper.Invoke.invoke;
33 import jdk.incubator.code.Op;
34 import jdk.incubator.code.bytecode.BytecodeGenerator;
35 import jdk.incubator.code.dialect.core.CoreOp;
36 import jdk.incubator.code.dialect.core.CoreType;
37 import jdk.incubator.code.dialect.java.JavaOp;
38 import jdk.incubator.code.dialect.java.JavaOp.InvokeOp.InvokeKind;
39 import jdk.incubator.code.dialect.java.JavaType;
40 import jdk.incubator.code.dialect.java.MethodRef;
41 import optkl.util.Regex;
42
43 import java.lang.invoke.MethodHandles;
44
45 public class SwapMath {
46 public static void main(String[] args) throws Throwable {
47 var lookup = MethodHandles.lookup();
48 MethodRef MathSqrt = MethodRef.method(Math.class, "sqrt", double.class, double.class);
49 MethodRef MathAbs = MethodRef.method(Math.class, "abs", double.class, double.class);
50
51 CoreOp.FuncOp rsqrt= CoreOp.func("rsqrt", CoreType.functionType(JavaType.DOUBLE, JavaType.DOUBLE))
52 .body(builder -> {// double rsqrt(double arg){return 1 / Math.sqrt(qrg)}
53 // var arg = builder.parameters().getFirst();
54 var argOp = CoreOp.var("arg", builder.parameters().getFirst());
55 var arg = builder.op(argOp);
56
57 // We can pass builder.parameters().getFirst() directly as arg below. But then we don't know the name
58 var sqrtInvoke = JavaOp.invoke(InvokeKind.STATIC, false, JavaType.DOUBLE, MathSqrt, arg);
59 var _1f = builder.op(CoreOp.constant(JavaType.DOUBLE, 1.0));
60
61 Op.Result invokeResult = builder.op(sqrtInvoke);
62 Op.Result divResult = builder.op(
63 JavaOp.div(_1f, invokeResult)
64 );
65 builder.op(CoreOp.return_(divResult));
66 });
67 var javaCodeBuilder = new JavaCodeBuilder<>(lookup,rsqrt);
68 System.out.println(rsqrt.toText());
69 System.out.println(javaCodeBuilder.toText());
70 System.out.println(" 1/sqrt(100) = " + BytecodeGenerator.generate(lookup, rsqrt).invoke(100));
71
72
73
74 System.out.println("--------------------------");
75 var abs = rsqrt.transform("usingAbs", (builder,op)->{
76 if (invoke(lookup,op) instanceof Invoke.Static ih
77 && ih.named("sqrt") && ih.returns(double.class) && ih.receives(double.class)){
78 var absStaticMethod = MethodRef.method(Math.class, "abs", double.class, double.class);
79 var absInvoke = JavaOp.invoke(InvokeKind.STATIC, false, absStaticMethod.type().returnType(), absStaticMethod,
80 builder.context().getValue(op.operands().get(0)));
81 var absResult= builder.op(absInvoke);
82 builder.context().mapValue(op.result(), absResult);
83 }else{
84 builder.op(op);
85 }
86 return builder;
87 });
88
89 System.out.println(abs.toText());
90 javaCodeBuilder = new JavaCodeBuilder<>(lookup,abs);
91 System.out.println(" 1/abs(100) = " + BytecodeGenerator.generate(MethodHandles.lookup(), abs).invoke(100));
92
93
94 System.out.println("Now using txfmr--------------------------");
95 var newAbs =Trxfmr.of(lookup,rsqrt)
96 .transform("usingAbs", ce-> invoke(lookup,ce) instanceof Invoke.Static $
97 && $.named("sqrt")
98 && $.returns(double.class)
99 && $.receives(double.class)
100 , c->
101 c.replace(JavaOp.invoke(InvokeKind.STATIC, false, JavaType.DOUBLE, MathAbs, c.mappedOperand( 0)))
102 )
103 .funcOp();
104
105
106 System.out.println(newAbs.toText());
107 javaCodeBuilder = new JavaCodeBuilder<>(lookup,newAbs);
108 System.out.println(javaCodeBuilder.toText());
109 System.out.println(" 1/abs(100) = " + BytecodeGenerator.generate(MethodHandles.lookup(), newAbs).invoke(100));
110
111
112 }
113 }
114