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 /*
25 * @test
26 * @modules jdk.incubator.code
27 * @run junit TestUsesDependsOn
28 */
29
30 import jdk.incubator.code.Block;
31 import jdk.incubator.code.Op;
32 import jdk.incubator.code.Value;
33 import jdk.incubator.code.dialect.java.JavaOp;
34 import jdk.incubator.code.extern.OpParser;
35 import org.junit.jupiter.api.Assertions;
36 import org.junit.jupiter.api.Test;
37
38 import java.util.HashMap;
39 import java.util.List;
40 import java.util.Map;
41 import java.util.Set;
42 import java.util.concurrent.atomic.AtomicInteger;
43 import java.util.function.BiConsumer;
44 import java.util.function.Function;
45
46 public class TestUsesDependsOn {
47
48 static final String OP = """
49 func @"f" (%0 : java.type:"int", %1 : java.type:"int")java.type:"int" -> {
50 %2 : java.type:"int" = add %0 %1;
51 %3 : java.type:"boolean" = lt %0 %1;
52 %4 : java.type:"void" = cbranch %3 ^b1(%2, %2) ^b2(%0, %1);
53
54 ^b1(%5 : java.type:"int", %6 : java.type:"int"):
55 %7 : java.type:"void" = return %5;
56
57 ^b2(%8 : java.type:"int", %9 : java.type:"int"):
58 %10 : java.type:"void" = return %8;
59 };
60 """;
61
62 @Test
63 public void testDependsOn() {
64 Op f = OpParser.fromText(JavaOp.JAVA_DIALECT_FACTORY, OP).get(0);
65
66 Map<String, List<String>> dependsUpon = computeValueMap(f, Value::dependsOn);
67
68 var expected = Map.ofEntries(
69 Map.entry("0", List.of()),
70 Map.entry("1", List.of()),
71 Map.entry("2", List.of("0", "1")),
72 Map.entry("3", List.of("0", "1")),
73 Map.entry("4", List.of("3", "2", "0", "1")),
74 Map.entry("5", List.of()),
75 Map.entry("6", List.of()),
76 Map.entry("7", List.of("5")),
77 Map.entry("8", List.of()),
78 Map.entry("9", List.of()),
79 Map.entry("10", List.of("8"))
80 );
81
82 Assertions.assertEquals(expected, dependsUpon);
83 }
84
85
86 @Test
87 public void testUses() {
88 Op f = OpParser.fromText(JavaOp.JAVA_DIALECT_FACTORY, OP).get(0);
89 System.out.println(f.toText());
90
91 Map<String, List<String>> uses = computeValueMap(f, Value::uses);
92
93 var expected = Map.ofEntries(
94 Map.entry("0", List.of("2", "3", "4")),
95 Map.entry("1", List.of("2", "3", "4")),
96 Map.entry("2", List.of("4")),
97 Map.entry("3", List.of("4")),
98 Map.entry("4", List.of()),
99 Map.entry("5", List.of("7")),
100 Map.entry("6", List.of()),
101 Map.entry("7", List.of()),
102 Map.entry("8", List.of("10")),
103 Map.entry("9", List.of()),
104 Map.entry("10", List.of())
105 );
106 System.out.println(uses.toString());
107 System.out.println(expected);
108
109 Assertions.assertEquals(expected, uses);
110 }
111
112 static Map<String, List<String>> computeValueMap(Op op, Function<Value, Set<? extends Value>> f) {
113 AtomicInteger ai = new AtomicInteger();
114
115 Map<Value, String> valueNameMap = computeValues(op, new HashMap<>(), (v, m) -> {
116 String name = Integer.toString(ai.getAndIncrement());
117 m.put(v, name);
118 });
119
120 return computeValues(op, new HashMap<>(), (v, m) -> {
121 m.put(valueNameMap.get(v), f.apply(v).stream().map(valueNameMap::get).toList());
122 });
123 }
124
125 static <T> T computeValues(Op op, T t, BiConsumer<Value, T> c) {
126 op.elements().forEach(e -> {
127 switch (e) {
128 case Block b -> {
129 for (var a : b.parameters()) {
130 c.accept(a, t);
131 }
132 }
133 case Op o -> {
134 if (o.result() != null) {
135 c.accept(o.result(), t);
136 }
137 }
138 default -> { }
139 }
140 });
141 return t;
142 }
143 }