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.dialect.java.JavaOp;
26 import jdk.incubator.code.dialect.java.JavaType;
27 import java.util.HashMap;
28 import java.util.Set;
29 import java.util.function.BiConsumer;
30 import java.util.function.Predicate;
31
32 import static jdk.incubator.code.dialect.java.JavaOp.sub;
33 import static jdk.incubator.code.analysis.Patterns.*;
34
35 public final class ExpressionElimination {
36 private ExpressionElimination() {
37 }
38
39 static final JavaType J_L_MATH = JavaType.type(Math.class);
40
41 static OpPattern negP(Pattern operand) {
42 return opP(JavaOp.NegOp.class, operand);
43 }
44
45 static OpPattern addP(Pattern lhs, Pattern rhs) {
46 return opP(JavaOp.AddOp.class, lhs, rhs);
47 }
48
49 static OpPattern mulP(Pattern lhs, Pattern rhs) {
50 return opP(JavaOp.MulOp.class, lhs, rhs);
51 }
52
53 public static <T extends Op> T eliminate(T f) {
54 // Note expression elimination and other forms of analysis is simplified if first of all expressions
55 // are normalized e.g. when they have an operand that is a constant expression
56 // and the operation is associative such as add(0, x) -> add(x, 0)
57
58 var actions = multiMatch(new HashMap<Op.Result, BiConsumer<Block.Builder, Op>>(), f)
59 .pattern(mulP(_P(), valueP(constantP(0.0d))))
60 .pattern(mulP(valueP(constantP(0.0d)), _P()))
61 .pattern(addP(valueP(), constantP(0.0d)))
62 .pattern(addP(constantP(0.0d), valueP()))
63 .pattern(mulP(constantP(1.0d), valueP()))
64 .pattern(mulP(valueP(), constantP(1.0d)))
65 .target((ms, as) -> {
66 Value a = ms.matchedOperands().get(0);
67 as.put(ms.op().result(), (block, op) -> {
68 CodeContext cc = block.context();
69 cc.mapValue(ms.op().result(), cc.getValue(a));
70 });
71 return as;
72 })
73 // add(neg(x), y) -> sub(y, x)
74 .pattern(addP(negP(valueP()), valueP()))
75 .target((ms, as) -> {
76 Value x = ms.matchedOperands().get(0);
77 Value y = ms.matchedOperands().get(1);
78
79 as.put(ms.op().result(), (block, op) -> {
80 CodeContext cc = block.context();
81 Op.Result r = block.op(sub(cc.getValue(y), cc.getValue(x)));
82 cc.mapValue(ms.op().result(), r);
83 });
84 return as;
85 })
86 .matchThenApply();
87
88 // Eliminate
89 Op ef = f.transform(CodeContext.create(), (block, op) -> {
90 BiConsumer<Block.Builder, Op> a = actions.get(op.result());
91 if (a != null) {
92 a.accept(block, op);
93 } else {
94 block.op(op);
95 }
96 return block;
97 });
98
99 Predicate<Op> testPure = op -> {
100 if (op instanceof Op.Pure) {
101 return true;
102 } else {
103 return op instanceof JavaOp.InvokeOp c && c.invokeDescriptor().refType().equals(J_L_MATH);
104 }
105 };
106
107 while (true) {
108 Set<Op> unused = matchUnusedPureOps(ef, testPure);
109 if (unused.isEmpty()) {
110 break;
111 }
112 // Remove unused ops
113 ef = ef.transform(CodeContext.create(), (block, op) -> {
114 if (!unused.contains(op)) {
115 block.op(op);
116 }
117 return block;
118 });
119 }
120
121 @SuppressWarnings("unchecked")
122 T t = (T) ef;
123 return t;
124 }
125 }