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 package org.graalvm.compiler.virtual.phases.ea; 24 25 import static org.graalvm.compiler.core.common.GraalOptions.ReadEliminationMaxLoopVisits; 26 import static org.graalvm.word.LocationIdentity.any; 27 28 import java.util.Iterator; 29 import java.util.List; 30 31 import org.graalvm.compiler.core.common.cfg.Loop; 32 import org.graalvm.compiler.core.common.type.Stamp; 33 import org.graalvm.compiler.graph.Node; 34 import org.graalvm.compiler.nodes.FieldLocationIdentity; 35 import org.graalvm.compiler.nodes.FixedWithNextNode; 36 import org.graalvm.compiler.nodes.LoopExitNode; 37 import org.graalvm.compiler.nodes.PhiNode; 38 import org.graalvm.compiler.nodes.ProxyNode; 39 import org.graalvm.compiler.nodes.ValueNode; 40 import org.graalvm.compiler.nodes.ValuePhiNode; 41 import org.graalvm.compiler.nodes.ValueProxyNode; 42 import org.graalvm.compiler.nodes.cfg.Block; 43 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; 44 import org.graalvm.compiler.nodes.extended.GuardedNode; 45 import org.graalvm.compiler.nodes.extended.GuardingNode; 46 import org.graalvm.compiler.nodes.extended.RawLoadNode; 47 import org.graalvm.compiler.nodes.extended.RawStoreNode; 48 import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; 49 import org.graalvm.compiler.nodes.java.AccessFieldNode; 50 import org.graalvm.compiler.nodes.java.LoadFieldNode; 51 import org.graalvm.compiler.nodes.java.StoreFieldNode; 52 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 53 import org.graalvm.compiler.nodes.memory.ReadNode; 54 import org.graalvm.compiler.nodes.memory.WriteNode; 55 import org.graalvm.compiler.nodes.util.GraphUtil; 56 import org.graalvm.compiler.options.OptionValues; 57 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; 58 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry; 59 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry; 60 import org.graalvm.util.EconomicMap; 61 import org.graalvm.util.EconomicSet; 62 import org.graalvm.util.Equivalence; 63 import org.graalvm.util.MapCursor; 64 import org.graalvm.word.LocationIdentity; 65 66 import jdk.vm.ci.meta.JavaKind; 67 68 /** 69 * This closure initially handled a set of nodes that is disjunct from 70 * {@link PEReadEliminationClosure}, but over time both have evolved so that there's a significant 71 * overlap. 72 */ 73 public final class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> { 74 private final boolean considerGuards; 129 } 130 } 131 } else if (node instanceof WriteNode) { 132 WriteNode write = (WriteNode) node; 133 if (write.getLocationIdentity().isSingle()) { 134 ValueNode object = GraphUtil.unproxify(write.getAddress()); 135 LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); 136 ValueNode cachedValue = state.getCacheEntry(identifier); 137 138 ValueNode value = getScalarAlias(write.value()); 139 if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { 140 effects.deleteNode(write); 141 deleted = true; 142 } 143 processIdentity(state, write.getLocationIdentity()); 144 state.addCacheEntry(identifier, value); 145 } else { 146 processIdentity(state, write.getLocationIdentity()); 147 } 148 } else if (node instanceof UnsafeAccessNode) { 149 if (node instanceof RawLoadNode) { 150 RawLoadNode load = (RawLoadNode) node; 151 if (load.getLocationIdentity().isSingle()) { 152 ValueNode object = GraphUtil.unproxify(load.object()); 153 UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity()); 154 ValueNode cachedValue = state.getCacheEntry(identifier); 155 if (cachedValue != null && areValuesReplaceable(load, cachedValue, considerGuards)) { 156 effects.replaceAtUsages(load, cachedValue, load); 157 addScalarAlias(load, cachedValue); 158 deleted = true; 159 } else { 160 state.addCacheEntry(identifier, load); 161 } 162 } 163 } else { 164 assert node instanceof RawStoreNode; 165 RawStoreNode write = (RawStoreNode) node; 166 if (write.getLocationIdentity().isSingle()) { 167 ValueNode object = GraphUtil.unproxify(write.object()); 168 UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity()); 169 ValueNode cachedValue = state.getCacheEntry(identifier); 170 171 ValueNode value = getScalarAlias(write.value()); 172 if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { 173 effects.deleteNode(write); 174 deleted = true; 175 } 176 processIdentity(state, write.getLocationIdentity()); 177 state.addCacheEntry(identifier, value); 178 } else { 179 processIdentity(state, write.getLocationIdentity()); 180 } 181 } 182 } else if (node instanceof MemoryCheckpoint.Single) { 183 LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); 184 processIdentity(state, identity); 185 } else if (node instanceof MemoryCheckpoint.Multi) { 186 for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { 187 processIdentity(state, identity); 188 } 189 } 190 return deleted; 191 } 192 193 private static boolean areValuesReplaceable(ValueNode originalValue, ValueNode replacementValue, boolean considerGuards) { 194 return originalValue.stamp().isCompatible(replacementValue.stamp()) && 195 (!considerGuards || (getGuard(originalValue) == null || getGuard(originalValue) == getGuard(replacementValue))); 196 } 197 198 private static GuardingNode getGuard(ValueNode node) { 199 if (node instanceof GuardedNode) { | 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 package org.graalvm.compiler.virtual.phases.ea; 24 25 import static org.graalvm.compiler.core.common.GraalOptions.ReadEliminationMaxLoopVisits; 26 import static org.graalvm.word.LocationIdentity.any; 27 28 import java.util.Iterator; 29 import java.util.List; 30 31 import jdk.vm.ci.meta.ResolvedJavaType; 32 import org.graalvm.compiler.core.common.cfg.Loop; 33 import org.graalvm.compiler.core.common.type.Stamp; 34 import org.graalvm.compiler.graph.Node; 35 import org.graalvm.compiler.nodes.FieldLocationIdentity; 36 import org.graalvm.compiler.nodes.FixedWithNextNode; 37 import org.graalvm.compiler.nodes.LoopExitNode; 38 import org.graalvm.compiler.nodes.PhiNode; 39 import org.graalvm.compiler.nodes.ProxyNode; 40 import org.graalvm.compiler.nodes.ValueNode; 41 import org.graalvm.compiler.nodes.ValuePhiNode; 42 import org.graalvm.compiler.nodes.ValueProxyNode; 43 import org.graalvm.compiler.nodes.cfg.Block; 44 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; 45 import org.graalvm.compiler.nodes.extended.GuardedNode; 46 import org.graalvm.compiler.nodes.extended.GuardingNode; 47 import org.graalvm.compiler.nodes.extended.RawLoadNode; 48 import org.graalvm.compiler.nodes.extended.RawStoreNode; 49 import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; 50 import org.graalvm.compiler.nodes.java.AccessFieldNode; 51 import org.graalvm.compiler.nodes.java.LoadFieldNode; 52 import org.graalvm.compiler.nodes.java.StoreFieldNode; 53 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; 54 import org.graalvm.compiler.nodes.memory.ReadNode; 55 import org.graalvm.compiler.nodes.memory.WriteNode; 56 import org.graalvm.compiler.nodes.type.StampTool; 57 import org.graalvm.compiler.nodes.util.GraphUtil; 58 import org.graalvm.compiler.options.OptionValues; 59 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.CacheEntry; 60 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry; 61 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry; 62 import org.graalvm.util.EconomicMap; 63 import org.graalvm.util.EconomicSet; 64 import org.graalvm.util.Equivalence; 65 import org.graalvm.util.MapCursor; 66 import org.graalvm.word.LocationIdentity; 67 68 import jdk.vm.ci.meta.JavaKind; 69 70 /** 71 * This closure initially handled a set of nodes that is disjunct from 72 * {@link PEReadEliminationClosure}, but over time both have evolved so that there's a significant 73 * overlap. 74 */ 75 public final class ReadEliminationClosure extends EffectsClosure<ReadEliminationBlockState> { 76 private final boolean considerGuards; 131 } 132 } 133 } else if (node instanceof WriteNode) { 134 WriteNode write = (WriteNode) node; 135 if (write.getLocationIdentity().isSingle()) { 136 ValueNode object = GraphUtil.unproxify(write.getAddress()); 137 LoadCacheEntry identifier = new LoadCacheEntry(object, write.getLocationIdentity()); 138 ValueNode cachedValue = state.getCacheEntry(identifier); 139 140 ValueNode value = getScalarAlias(write.value()); 141 if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { 142 effects.deleteNode(write); 143 deleted = true; 144 } 145 processIdentity(state, write.getLocationIdentity()); 146 state.addCacheEntry(identifier, value); 147 } else { 148 processIdentity(state, write.getLocationIdentity()); 149 } 150 } else if (node instanceof UnsafeAccessNode) { 151 ResolvedJavaType type = StampTool.typeOrNull(((UnsafeAccessNode) node).object()); 152 if (type != null && !type.isArray()) { 153 if (node instanceof RawLoadNode) { 154 RawLoadNode load = (RawLoadNode) node; 155 if (load.getLocationIdentity().isSingle()) { 156 ValueNode object = GraphUtil.unproxify(load.object()); 157 UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, load.offset(), load.getLocationIdentity()); 158 ValueNode cachedValue = state.getCacheEntry(identifier); 159 if (cachedValue != null && areValuesReplaceable(load, cachedValue, considerGuards)) { 160 effects.replaceAtUsages(load, cachedValue, load); 161 addScalarAlias(load, cachedValue); 162 deleted = true; 163 } else { 164 state.addCacheEntry(identifier, load); 165 } 166 } 167 } else { 168 assert node instanceof RawStoreNode; 169 RawStoreNode write = (RawStoreNode) node; 170 if (write.getLocationIdentity().isSingle()) { 171 ValueNode object = GraphUtil.unproxify(write.object()); 172 UnsafeLoadCacheEntry identifier = new UnsafeLoadCacheEntry(object, write.offset(), write.getLocationIdentity()); 173 ValueNode cachedValue = state.getCacheEntry(identifier); 174 175 ValueNode value = getScalarAlias(write.value()); 176 if (GraphUtil.unproxify(value) == GraphUtil.unproxify(cachedValue)) { 177 effects.deleteNode(write); 178 deleted = true; 179 } 180 processIdentity(state, write.getLocationIdentity()); 181 state.addCacheEntry(identifier, value); 182 } else { 183 processIdentity(state, write.getLocationIdentity()); 184 } 185 } 186 } 187 } else if (node instanceof MemoryCheckpoint.Single) { 188 LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity(); 189 processIdentity(state, identity); 190 } else if (node instanceof MemoryCheckpoint.Multi) { 191 for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) { 192 processIdentity(state, identity); 193 } 194 } 195 return deleted; 196 } 197 198 private static boolean areValuesReplaceable(ValueNode originalValue, ValueNode replacementValue, boolean considerGuards) { 199 return originalValue.stamp().isCompatible(replacementValue.stamp()) && 200 (!considerGuards || (getGuard(originalValue) == null || getGuard(originalValue) == getGuard(replacementValue))); 201 } 202 203 private static GuardingNode getGuard(ValueNode node) { 204 if (node instanceof GuardedNode) { |