52 import org.graalvm.compiler.graph.spi.SimplifierTool; |
52 import org.graalvm.compiler.graph.spi.SimplifierTool; |
53 import org.graalvm.compiler.nodes.AbstractBeginNode; |
53 import org.graalvm.compiler.nodes.AbstractBeginNode; |
54 import org.graalvm.compiler.nodes.AbstractEndNode; |
54 import org.graalvm.compiler.nodes.AbstractEndNode; |
55 import org.graalvm.compiler.nodes.AbstractMergeNode; |
55 import org.graalvm.compiler.nodes.AbstractMergeNode; |
56 import org.graalvm.compiler.nodes.ConstantNode; |
56 import org.graalvm.compiler.nodes.ConstantNode; |
|
57 import org.graalvm.compiler.nodes.ControlSinkNode; |
57 import org.graalvm.compiler.nodes.ControlSplitNode; |
58 import org.graalvm.compiler.nodes.ControlSplitNode; |
58 import org.graalvm.compiler.nodes.FixedNode; |
59 import org.graalvm.compiler.nodes.FixedNode; |
59 import org.graalvm.compiler.nodes.FixedWithNextNode; |
60 import org.graalvm.compiler.nodes.FixedWithNextNode; |
60 import org.graalvm.compiler.nodes.FrameState; |
61 import org.graalvm.compiler.nodes.FrameState; |
61 import org.graalvm.compiler.nodes.GuardNode; |
62 import org.graalvm.compiler.nodes.GuardNode; |
|
63 import org.graalvm.compiler.nodes.IfNode; |
62 import org.graalvm.compiler.nodes.LoopBeginNode; |
64 import org.graalvm.compiler.nodes.LoopBeginNode; |
63 import org.graalvm.compiler.nodes.LoopEndNode; |
65 import org.graalvm.compiler.nodes.LoopEndNode; |
64 import org.graalvm.compiler.nodes.LoopExitNode; |
66 import org.graalvm.compiler.nodes.LoopExitNode; |
65 import org.graalvm.compiler.nodes.NodeView; |
67 import org.graalvm.compiler.nodes.NodeView; |
66 import org.graalvm.compiler.nodes.PhiNode; |
68 import org.graalvm.compiler.nodes.PhiNode; |
103 public static class Options { |
105 public static class Options { |
104 @Option(help = "Verify that there are no new unused nodes when performing killCFG", type = OptionType.Debug)// |
106 @Option(help = "Verify that there are no new unused nodes when performing killCFG", type = OptionType.Debug)// |
105 public static final OptionKey<Boolean> VerifyKillCFGUnusedNodes = new OptionKey<>(false); |
107 public static final OptionKey<Boolean> VerifyKillCFGUnusedNodes = new OptionKey<>(false); |
106 } |
108 } |
107 |
109 |
|
110 public static final int MAX_FRAMESTATE_SEARCH_DEPTH = 4; |
|
111 |
108 private static void killCFGInner(FixedNode node) { |
112 private static void killCFGInner(FixedNode node) { |
109 EconomicSet<Node> markedNodes = EconomicSet.create(); |
113 EconomicSet<Node> markedNodes = EconomicSet.create(); |
110 EconomicMap<AbstractMergeNode, List<AbstractEndNode>> unmarkedMerges = EconomicMap.create(); |
114 EconomicMap<AbstractMergeNode, List<AbstractEndNode>> unmarkedMerges = EconomicMap.create(); |
111 |
115 |
112 // Detach this node from CFG |
116 // Detach this node from CFG |
1108 /* Perform the replacement. */ |
1112 /* Perform the replacement. */ |
1109 VirtualArrayNode newVirtualArray = virtualArrayProvider.apply(newComponentType, newLengthInt); |
1113 VirtualArrayNode newVirtualArray = virtualArrayProvider.apply(newComponentType, newLengthInt); |
1110 tool.createVirtualObject(newVirtualArray, newEntryState, Collections.<MonitorIdNode> emptyList(), false); |
1114 tool.createVirtualObject(newVirtualArray, newEntryState, Collections.<MonitorIdNode> emptyList(), false); |
1111 tool.replaceWithVirtual(newVirtualArray); |
1115 tool.replaceWithVirtual(newVirtualArray); |
1112 } |
1116 } |
|
1117 |
|
1118 /** |
|
1119 * Snippet lowerings may produce patterns without a frame state on the merge. We need to take |
|
1120 * extra care when optimizing these patterns. |
|
1121 */ |
|
1122 public static boolean checkFrameState(FixedNode start, int maxDepth) { |
|
1123 if (maxDepth == 0) { |
|
1124 return false; |
|
1125 } |
|
1126 FixedNode node = start; |
|
1127 while (true) { |
|
1128 if (node instanceof AbstractMergeNode) { |
|
1129 AbstractMergeNode mergeNode = (AbstractMergeNode) node; |
|
1130 if (mergeNode.stateAfter() == null) { |
|
1131 return false; |
|
1132 } else { |
|
1133 return true; |
|
1134 } |
|
1135 } else if (node instanceof StateSplit) { |
|
1136 StateSplit stateSplitNode = (StateSplit) node; |
|
1137 if (stateSplitNode.stateAfter() != null) { |
|
1138 return true; |
|
1139 } |
|
1140 } |
|
1141 |
|
1142 if (node instanceof ControlSplitNode) { |
|
1143 ControlSplitNode controlSplitNode = (ControlSplitNode) node; |
|
1144 for (Node succ : controlSplitNode.cfgSuccessors()) { |
|
1145 if (checkFrameState((FixedNode) succ, maxDepth - 1)) { |
|
1146 return true; |
|
1147 } |
|
1148 } |
|
1149 return false; |
|
1150 } else if (node instanceof FixedWithNextNode) { |
|
1151 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) node; |
|
1152 node = fixedWithNextNode.next(); |
|
1153 } else if (node instanceof AbstractEndNode) { |
|
1154 AbstractEndNode endNode = (AbstractEndNode) node; |
|
1155 node = endNode.merge(); |
|
1156 } else if (node instanceof ControlSinkNode) { |
|
1157 return true; |
|
1158 } else { |
|
1159 assert false : "unexpected node"; |
|
1160 return false; |
|
1161 } |
|
1162 } |
|
1163 } |
|
1164 |
|
1165 public static boolean mayRemoveSplit(IfNode ifNode) { |
|
1166 return GraphUtil.checkFrameState(ifNode.trueSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH) && GraphUtil.checkFrameState(ifNode.falseSuccessor(), MAX_FRAMESTATE_SEARCH_DEPTH); |
|
1167 } |
1113 } |
1168 } |