64 import jdk.vm.ci.meta.ConstantReflectionProvider; |
70 import jdk.vm.ci.meta.ConstantReflectionProvider; |
65 import jdk.vm.ci.meta.MetaAccessProvider; |
71 import jdk.vm.ci.meta.MetaAccessProvider; |
66 |
72 |
67 public class CanonicalizerPhase extends BasePhase<CoreProviders> { |
73 public class CanonicalizerPhase extends BasePhase<CoreProviders> { |
68 |
74 |
|
75 public enum CanonicalizerFeature { |
|
76 READ_CANONICALIZATION, |
|
77 CFG_SIMPLIFICATION, |
|
78 GVN |
|
79 } |
|
80 |
69 private static final int MAX_ITERATION_PER_NODE = 10; |
81 private static final int MAX_ITERATION_PER_NODE = 10; |
70 private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes"); |
82 private static final CounterKey COUNTER_CANONICALIZED_NODES = DebugContext.counter("CanonicalizedNodes"); |
71 private static final CounterKey COUNTER_PROCESSED_NODES = DebugContext.counter("ProcessedNodes"); |
83 private static final CounterKey COUNTER_PROCESSED_NODES = DebugContext.counter("ProcessedNodes"); |
72 private static final CounterKey COUNTER_CANONICALIZATION_CONSIDERED_NODES = DebugContext.counter("CanonicalizationConsideredNodes"); |
84 private static final CounterKey COUNTER_CANONICALIZATION_CONSIDERED_NODES = DebugContext.counter("CanonicalizationConsideredNodes"); |
73 private static final CounterKey COUNTER_INFER_STAMP_CALLED = DebugContext.counter("InferStampCalled"); |
85 private static final CounterKey COUNTER_INFER_STAMP_CALLED = DebugContext.counter("InferStampCalled"); |
74 private static final CounterKey COUNTER_STAMP_CHANGED = DebugContext.counter("StampChanged"); |
86 private static final CounterKey COUNTER_STAMP_CHANGED = DebugContext.counter("StampChanged"); |
75 private static final CounterKey COUNTER_SIMPLIFICATION_CONSIDERED_NODES = DebugContext.counter("SimplificationConsideredNodes"); |
87 private static final CounterKey COUNTER_SIMPLIFICATION_CONSIDERED_NODES = DebugContext.counter("SimplificationConsideredNodes"); |
76 private static final CounterKey COUNTER_GLOBAL_VALUE_NUMBERING_HITS = DebugContext.counter("GlobalValueNumberingHits"); |
88 private static final CounterKey COUNTER_GLOBAL_VALUE_NUMBERING_HITS = DebugContext.counter("GlobalValueNumberingHits"); |
77 |
89 |
78 private boolean globalValueNumber = true; |
90 private final EnumSet<CanonicalizerFeature> features; |
79 private boolean canonicalizeReads = true; |
91 private final CustomCanonicalization customCanonicalization; |
80 private boolean simplify = true; |
92 private final CustomSimplification customSimplification; |
81 private final CustomCanonicalizer customCanonicalizer; |
93 |
82 |
94 public interface CustomCanonicalization { |
83 public abstract static class CustomCanonicalizer { |
95 /** |
84 |
96 * @param node the node to be canonicalized |
85 public Node canonicalize(Node node) { |
97 * @return the same node if no action should be taken, {@code null} if the node should be |
86 return node; |
98 * deleted, or a new node that should replace the given node |
87 } |
99 */ |
88 |
100 Node canonicalize(Node node); |
89 @SuppressWarnings("unused") |
101 } |
90 public void simplify(Node node, SimplifierTool tool) { |
102 |
91 } |
103 public interface CustomSimplification { |
92 } |
104 /** |
93 |
105 * @param node the node to be simplified |
94 public CanonicalizerPhase() { |
106 * @param tool utility available during the simplification process |
95 this(null); |
107 */ |
96 } |
108 void simplify(Node node, SimplifierTool tool); |
97 |
109 } |
98 public CanonicalizerPhase(CustomCanonicalizer customCanonicalizer) { |
110 |
99 this.customCanonicalizer = customCanonicalizer; |
111 protected CanonicalizerPhase(EnumSet<CanonicalizerFeature> features) { |
100 } |
112 this(null, null, features); |
101 |
113 } |
102 public void disableGVN() { |
114 |
103 globalValueNumber = false; |
115 protected CanonicalizerPhase() { |
104 } |
116 this(null, null, EnumSet.allOf(CanonicalizerFeature.class)); |
105 |
117 } |
106 public void disableReadCanonicalization() { |
118 |
107 canonicalizeReads = false; |
119 protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification) { |
108 } |
120 this(customCanonicalization, customSimplification, EnumSet.allOf(CanonicalizerFeature.class)); |
109 |
121 } |
110 public void disableSimplification() { |
122 |
111 simplify = false; |
123 protected CanonicalizerPhase(CustomCanonicalization customCanonicalization, CustomSimplification customSimplification, EnumSet<CanonicalizerFeature> features) { |
|
124 this.customCanonicalization = customCanonicalization; |
|
125 this.customSimplification = customSimplification; |
|
126 this.features = features; |
|
127 } |
|
128 |
|
129 public CanonicalizerPhase copyWithCustomCanonicalization(CustomCanonicalization newCanonicalization) { |
|
130 return new CanonicalizerPhase(newCanonicalization, customSimplification, features); |
|
131 } |
|
132 |
|
133 public CanonicalizerPhase copyWithCustomSimplification(CustomSimplification newSimplification) { |
|
134 return new CanonicalizerPhase(customCanonicalization, newSimplification, features); |
|
135 } |
|
136 |
|
137 public CanonicalizerPhase copyWithoutGVN() { |
|
138 EnumSet<CanonicalizerFeature> newFeatures = EnumSet.copyOf(features); |
|
139 newFeatures.remove(GVN); |
|
140 return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures); |
|
141 } |
|
142 |
|
143 public CanonicalizerPhase copyWithoutSimplification() { |
|
144 EnumSet<CanonicalizerFeature> newFeatures = EnumSet.copyOf(features); |
|
145 newFeatures.remove(CFG_SIMPLIFICATION); |
|
146 return new CanonicalizerPhase(customCanonicalization, customSimplification, newFeatures); |
|
147 } |
|
148 |
|
149 public static CanonicalizerPhase create() { |
|
150 return new CanonicalizerPhase(null, null, EnumSet.allOf(CanonicalizerFeature.class)); |
|
151 } |
|
152 |
|
153 public static CanonicalizerPhase createWithoutReadCanonicalization() { |
|
154 return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(READ_CANONICALIZATION))); |
|
155 } |
|
156 |
|
157 public static CanonicalizerPhase createWithoutGVN() { |
|
158 return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(GVN))); |
|
159 } |
|
160 |
|
161 public static CanonicalizerPhase createWithoutCFGSimplification() { |
|
162 return new CanonicalizerPhase(EnumSet.complementOf(EnumSet.of(CFG_SIMPLIFICATION))); |
112 } |
163 } |
113 |
164 |
114 @Override |
165 @Override |
115 public boolean checkContract() { |
166 public boolean checkContract() { |
116 /* |
167 /* |
327 } |
378 } |
328 |
379 |
329 @SuppressWarnings("try") |
380 @SuppressWarnings("try") |
330 public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) { |
381 public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) { |
331 try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.withContext(node)) { |
382 try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.withContext(node)) { |
332 if (customCanonicalizer != null) { |
|
333 Node canonical = customCanonicalizer.canonicalize(node); |
|
334 if (performReplacement(node, canonical)) { |
|
335 return true; |
|
336 } else { |
|
337 customCanonicalizer.simplify(node, tool); |
|
338 if (node.isDeleted()) { |
|
339 return true; |
|
340 } |
|
341 } |
|
342 } |
|
343 if (nodeClass.isCanonicalizable()) { |
383 if (nodeClass.isCanonicalizable()) { |
344 COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(debug); |
384 COUNTER_CANONICALIZATION_CONSIDERED_NODES.increment(debug); |
345 Node canonical; |
385 Node canonical = node; |
346 try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) { |
386 try (AutoCloseable verify = getCanonicalizeableContractAssertion(node)) { |
347 canonical = ((Canonicalizable) node).canonical(tool); |
387 if (customCanonicalization != null) { |
348 if (canonical == node && nodeClass.isCommutative()) { |
388 canonical = customCanonicalization.canonicalize(node); |
349 canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs(); |
389 } |
|
390 if (canonical == node) { |
|
391 canonical = ((Canonicalizable) node).canonical(tool); |
|
392 if (canonical == node && nodeClass.isCommutative()) { |
|
393 canonical = ((BinaryCommutative<?>) node).maybeCommuteInputs(); |
|
394 } |
350 } |
395 } |
351 } catch (Throwable e) { |
396 } catch (Throwable e) { |
352 throw new GraalGraphError(e).addContext(node); |
397 throw new GraalGraphError(e).addContext(node); |
353 } |
398 } |
354 if (performReplacement(node, canonical)) { |
399 if (performReplacement(node, canonical)) { |
355 return true; |
400 return true; |
356 } |
401 } |
357 } |
402 } |
358 |
403 |
359 if (nodeClass.isSimplifiable() && simplify) { |
404 if (features.contains(CFG_SIMPLIFICATION) && nodeClass.isSimplifiable()) { |
360 debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node); |
405 debug.log(DebugContext.VERBOSE_LEVEL, "Canonicalizer: simplifying %s", node); |
361 COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug); |
406 COUNTER_SIMPLIFICATION_CONSIDERED_NODES.increment(debug); |
362 node.simplify(tool); |
407 if (customSimplification != null) { |
363 if (node.isDeleted()) { |
408 customSimplification.simplify(node, tool); |
364 debug.log("Canonicalizer: simplified %s", node); |
409 } |
|
410 if (node.isAlive()) { |
|
411 node.simplify(tool); |
|
412 if (node.isDeleted()) { |
|
413 debug.log("Canonicalizer: simplified %s", node); |
|
414 } |
365 } |
415 } |
366 return node.isDeleted(); |
416 return node.isDeleted(); |
367 } |
417 } |
368 return false; |
418 return false; |
369 } catch (Throwable throwable) { |
419 } catch (Throwable throwable) { |