src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java

Print this page




  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.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION;
  27 
  28 import java.util.EnumMap;
  29 import java.util.Iterator;
  30 import java.util.List;
  31 
  32 import org.graalvm.compiler.core.common.cfg.Loop;
  33 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
  34 import org.graalvm.compiler.debug.Debug;
  35 import org.graalvm.compiler.graph.Node;

  36 import org.graalvm.compiler.nodes.FieldLocationIdentity;
  37 import org.graalvm.compiler.nodes.FixedNode;
  38 import org.graalvm.compiler.nodes.FixedWithNextNode;
  39 import org.graalvm.compiler.nodes.LoopBeginNode;
  40 import org.graalvm.compiler.nodes.LoopExitNode;
  41 import org.graalvm.compiler.nodes.NamedLocationIdentity;
  42 import org.graalvm.compiler.nodes.PhiNode;
  43 import org.graalvm.compiler.nodes.ProxyNode;
  44 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
  45 import org.graalvm.compiler.nodes.ValueNode;
  46 import org.graalvm.compiler.nodes.ValueProxyNode;
  47 import org.graalvm.compiler.nodes.cfg.Block;
  48 import org.graalvm.compiler.nodes.extended.UnboxNode;
  49 import org.graalvm.compiler.nodes.extended.RawLoadNode;
  50 import org.graalvm.compiler.nodes.extended.RawStoreNode;

  51 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
  52 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  53 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
  54 import org.graalvm.compiler.nodes.java.StoreFieldNode;
  55 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
  56 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
  57 import org.graalvm.compiler.nodes.spi.LoweringProvider;
  58 import org.graalvm.compiler.nodes.type.StampTool;
  59 import org.graalvm.compiler.nodes.util.GraphUtil;
  60 import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
  61 import org.graalvm.compiler.options.OptionValues;
  62 import org.graalvm.compiler.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry;
  63 import org.graalvm.util.EconomicMap;
  64 import org.graalvm.util.EconomicSet;
  65 import org.graalvm.util.Equivalence;
  66 import org.graalvm.util.MapCursor;
  67 import org.graalvm.util.Pair;
  68 import org.graalvm.word.LocationIdentity;
  69 
  70 import jdk.vm.ci.meta.ConstantReflectionProvider;


  74 import jdk.vm.ci.meta.ResolvedJavaType;
  75 
  76 public final class PEReadEliminationClosure extends PartialEscapeClosure<PEReadEliminationBlockState> {
  77 
  78     private static final EnumMap<JavaKind, LocationIdentity> UNBOX_LOCATIONS;
  79 
  80     static {
  81         UNBOX_LOCATIONS = new EnumMap<>(JavaKind.class);
  82         for (JavaKind kind : JavaKind.values()) {
  83             UNBOX_LOCATIONS.put(kind, NamedLocationIdentity.immutable("PEA unbox " + kind.getJavaName()));
  84         }
  85     }
  86 
  87     public PEReadEliminationClosure(ScheduleResult schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider,
  88                     LoweringProvider loweringProvider) {
  89         super(schedule, metaAccess, constantReflection, constantFieldProvider, loweringProvider);
  90     }
  91 
  92     @Override
  93     protected PEReadEliminationBlockState getInitialState() {
  94         return new PEReadEliminationBlockState(tool.getOptions());
  95     }
  96 
  97     @Override
  98     protected boolean processNode(Node node, PEReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
  99         if (super.processNode(node, state, effects, lastFixedNode)) {
 100             return true;
 101         }
 102 
 103         if (node instanceof LoadFieldNode) {
 104             return processLoadField((LoadFieldNode) node, state, effects);
 105         } else if (node instanceof StoreFieldNode) {
 106             return processStoreField((StoreFieldNode) node, state, effects);
 107         } else if (node instanceof LoadIndexedNode) {
 108             return processLoadIndexed((LoadIndexedNode) node, state, effects);
 109         } else if (node instanceof StoreIndexedNode) {
 110             return processStoreIndexed((StoreIndexedNode) node, state, effects);
 111         } else if (node instanceof ArrayLengthNode) {
 112             return processArrayLength((ArrayLengthNode) node, state, effects);
 113         } else if (node instanceof UnboxNode) {
 114             return processUnbox((UnboxNode) node, state, effects);
 115         } else if (node instanceof RawLoadNode) {
 116             return processUnsafeLoad((RawLoadNode) node, state, effects);
 117         } else if (node instanceof RawStoreNode) {
 118             return processUnsafeStore((RawStoreNode) node, state, effects);
 119         } else if (node instanceof MemoryCheckpoint.Single) {
 120             COUNTER_MEMORYCHECKPOINT.increment();
 121             LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
 122             processIdentity(state, identity);
 123         } else if (node instanceof MemoryCheckpoint.Multi) {
 124             COUNTER_MEMORYCHECKPOINT.increment();
 125             for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) {
 126                 processIdentity(state, identity);
 127             }
 128         }
 129 
 130         return false;
 131     }
 132 
 133     private boolean processStore(FixedNode store, ValueNode object, LocationIdentity identity, int index, ValueNode value, PEReadEliminationBlockState state, GraphEffectList effects) {
 134         ValueNode unproxiedObject = GraphUtil.unproxify(object);
 135         ValueNode cachedValue = state.getReadCache(object, identity, index, this);
 136 
 137         ValueNode finalValue = getScalarAlias(value);
 138         boolean result = false;
 139         if (GraphUtil.unproxify(finalValue) == GraphUtil.unproxify(cachedValue)) {
 140             effects.deleteNode(store);
 141             result = true;
 142         }
 143         state.killReadCache(identity, index);
 144         state.addReadCache(unproxiedObject, identity, index, finalValue, this);


 409                 for (int i = 0; i < values.length; i++) {
 410                     setPhiInput(phiNode, i, values[i]);
 411                 }
 412                 newState.readCache.put(new ReadCacheEntry(identity, phi, index), phiNode);
 413             }
 414         }
 415     }
 416 
 417     @Override
 418     protected void processKilledLoopLocations(Loop<Block> loop, PEReadEliminationBlockState initialState, PEReadEliminationBlockState mergedStates) {
 419         assert initialState != null;
 420         assert mergedStates != null;
 421         if (initialState.readCache.size() > 0) {
 422             LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop);
 423             // we have fully processed this loop the first time, remember to cache it the next time
 424             // it is visited
 425             if (loopKilledLocations == null) {
 426                 loopKilledLocations = new LoopKillCache(1/* 1.visit */);
 427                 loopLocationKillCache.put(loop, loopKilledLocations);
 428             } else {
 429                 OptionValues options = loop.getHeader().getBeginNode().getOptions();

 430                 if (loopKilledLocations.visits() > ReadEliminationMaxLoopVisits.getValue(options)) {
 431                     // we have processed the loop too many times, kill all locations so the inner
 432                     // loop will never be processed more than once again on visit
 433                     loopKilledLocations.setKillsAll();
 434                 } else {
 435                     // we have fully processed this loop >1 times, update the killed locations
 436                     EconomicSet<LocationIdentity> forwardEndLiveLocations = EconomicSet.create(Equivalence.DEFAULT);
 437                     for (ReadCacheEntry entry : initialState.readCache.getKeys()) {
 438                         forwardEndLiveLocations.add(entry.identity);
 439                     }
 440                     for (ReadCacheEntry entry : mergedStates.readCache.getKeys()) {
 441                         forwardEndLiveLocations.remove(entry.identity);
 442                     }
 443                     // every location that is alive before the loop but not after is killed by the
 444                     // loop
 445                     for (LocationIdentity location : forwardEndLiveLocations) {
 446                         loopKilledLocations.rememberLoopKilledLocation(location);
 447                     }
 448                     if (Debug.isLogEnabled() && loopKilledLocations != null) {
 449                         Debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s",
 450                                         loop.getHeader().getBeginNode(), forwardEndLiveLocations);
 451                     }
 452                 }
 453                 // remember the loop visit
 454                 loopKilledLocations.visited();
 455             }
 456         }
 457     }
 458 
 459     @Override
 460     protected PEReadEliminationBlockState stripKilledLoopLocations(Loop<Block> loop, PEReadEliminationBlockState originalInitialState) {
 461         PEReadEliminationBlockState initialState = super.stripKilledLoopLocations(loop, originalInitialState);
 462         LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop);
 463         if (loopKilledLocations != null && loopKilledLocations.loopKillsLocations()) {
 464             Iterator<ReadCacheEntry> it = initialState.readCache.getKeys().iterator();
 465             while (it.hasNext()) {
 466                 ReadCacheEntry entry = it.next();
 467                 if (loopKilledLocations.containsLocation(entry.identity)) {
 468                     it.remove();
 469                 }
 470             }


  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.compiler.nodes.NamedLocationIdentity.ARRAY_LENGTH_LOCATION;
  27 
  28 import java.util.EnumMap;
  29 import java.util.Iterator;
  30 import java.util.List;
  31 
  32 import org.graalvm.compiler.core.common.cfg.Loop;
  33 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;

  34 import org.graalvm.compiler.graph.Node;
  35 import org.graalvm.compiler.nodes.AbstractBeginNode;
  36 import org.graalvm.compiler.nodes.FieldLocationIdentity;
  37 import org.graalvm.compiler.nodes.FixedNode;
  38 import org.graalvm.compiler.nodes.FixedWithNextNode;
  39 import org.graalvm.compiler.nodes.LoopBeginNode;
  40 import org.graalvm.compiler.nodes.LoopExitNode;
  41 import org.graalvm.compiler.nodes.NamedLocationIdentity;
  42 import org.graalvm.compiler.nodes.PhiNode;
  43 import org.graalvm.compiler.nodes.ProxyNode;
  44 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
  45 import org.graalvm.compiler.nodes.ValueNode;
  46 import org.graalvm.compiler.nodes.ValueProxyNode;
  47 import org.graalvm.compiler.nodes.cfg.Block;

  48 import org.graalvm.compiler.nodes.extended.RawLoadNode;
  49 import org.graalvm.compiler.nodes.extended.RawStoreNode;
  50 import org.graalvm.compiler.nodes.extended.UnboxNode;
  51 import org.graalvm.compiler.nodes.java.ArrayLengthNode;
  52 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  53 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
  54 import org.graalvm.compiler.nodes.java.StoreFieldNode;
  55 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
  56 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
  57 import org.graalvm.compiler.nodes.spi.LoweringProvider;
  58 import org.graalvm.compiler.nodes.type.StampTool;
  59 import org.graalvm.compiler.nodes.util.GraphUtil;
  60 import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
  61 import org.graalvm.compiler.options.OptionValues;
  62 import org.graalvm.compiler.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry;
  63 import org.graalvm.util.EconomicMap;
  64 import org.graalvm.util.EconomicSet;
  65 import org.graalvm.util.Equivalence;
  66 import org.graalvm.util.MapCursor;
  67 import org.graalvm.util.Pair;
  68 import org.graalvm.word.LocationIdentity;
  69 
  70 import jdk.vm.ci.meta.ConstantReflectionProvider;


  74 import jdk.vm.ci.meta.ResolvedJavaType;
  75 
  76 public final class PEReadEliminationClosure extends PartialEscapeClosure<PEReadEliminationBlockState> {
  77 
  78     private static final EnumMap<JavaKind, LocationIdentity> UNBOX_LOCATIONS;
  79 
  80     static {
  81         UNBOX_LOCATIONS = new EnumMap<>(JavaKind.class);
  82         for (JavaKind kind : JavaKind.values()) {
  83             UNBOX_LOCATIONS.put(kind, NamedLocationIdentity.immutable("PEA unbox " + kind.getJavaName()));
  84         }
  85     }
  86 
  87     public PEReadEliminationClosure(ScheduleResult schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider,
  88                     LoweringProvider loweringProvider) {
  89         super(schedule, metaAccess, constantReflection, constantFieldProvider, loweringProvider);
  90     }
  91 
  92     @Override
  93     protected PEReadEliminationBlockState getInitialState() {
  94         return new PEReadEliminationBlockState(tool.getOptions(), tool.getDebug());
  95     }
  96 
  97     @Override
  98     protected boolean processNode(Node node, PEReadEliminationBlockState state, GraphEffectList effects, FixedWithNextNode lastFixedNode) {
  99         if (super.processNode(node, state, effects, lastFixedNode)) {
 100             return true;
 101         }
 102 
 103         if (node instanceof LoadFieldNode) {
 104             return processLoadField((LoadFieldNode) node, state, effects);
 105         } else if (node instanceof StoreFieldNode) {
 106             return processStoreField((StoreFieldNode) node, state, effects);
 107         } else if (node instanceof LoadIndexedNode) {
 108             return processLoadIndexed((LoadIndexedNode) node, state, effects);
 109         } else if (node instanceof StoreIndexedNode) {
 110             return processStoreIndexed((StoreIndexedNode) node, state, effects);
 111         } else if (node instanceof ArrayLengthNode) {
 112             return processArrayLength((ArrayLengthNode) node, state, effects);
 113         } else if (node instanceof UnboxNode) {
 114             return processUnbox((UnboxNode) node, state, effects);
 115         } else if (node instanceof RawLoadNode) {
 116             return processUnsafeLoad((RawLoadNode) node, state, effects);
 117         } else if (node instanceof RawStoreNode) {
 118             return processUnsafeStore((RawStoreNode) node, state, effects);
 119         } else if (node instanceof MemoryCheckpoint.Single) {
 120             COUNTER_MEMORYCHECKPOINT.increment(node.getDebug());
 121             LocationIdentity identity = ((MemoryCheckpoint.Single) node).getLocationIdentity();
 122             processIdentity(state, identity);
 123         } else if (node instanceof MemoryCheckpoint.Multi) {
 124             COUNTER_MEMORYCHECKPOINT.increment(node.getDebug());
 125             for (LocationIdentity identity : ((MemoryCheckpoint.Multi) node).getLocationIdentities()) {
 126                 processIdentity(state, identity);
 127             }
 128         }
 129 
 130         return false;
 131     }
 132 
 133     private boolean processStore(FixedNode store, ValueNode object, LocationIdentity identity, int index, ValueNode value, PEReadEliminationBlockState state, GraphEffectList effects) {
 134         ValueNode unproxiedObject = GraphUtil.unproxify(object);
 135         ValueNode cachedValue = state.getReadCache(object, identity, index, this);
 136 
 137         ValueNode finalValue = getScalarAlias(value);
 138         boolean result = false;
 139         if (GraphUtil.unproxify(finalValue) == GraphUtil.unproxify(cachedValue)) {
 140             effects.deleteNode(store);
 141             result = true;
 142         }
 143         state.killReadCache(identity, index);
 144         state.addReadCache(unproxiedObject, identity, index, finalValue, this);


 409                 for (int i = 0; i < values.length; i++) {
 410                     setPhiInput(phiNode, i, values[i]);
 411                 }
 412                 newState.readCache.put(new ReadCacheEntry(identity, phi, index), phiNode);
 413             }
 414         }
 415     }
 416 
 417     @Override
 418     protected void processKilledLoopLocations(Loop<Block> loop, PEReadEliminationBlockState initialState, PEReadEliminationBlockState mergedStates) {
 419         assert initialState != null;
 420         assert mergedStates != null;
 421         if (initialState.readCache.size() > 0) {
 422             LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop);
 423             // we have fully processed this loop the first time, remember to cache it the next time
 424             // it is visited
 425             if (loopKilledLocations == null) {
 426                 loopKilledLocations = new LoopKillCache(1/* 1.visit */);
 427                 loopLocationKillCache.put(loop, loopKilledLocations);
 428             } else {
 429                 AbstractBeginNode beginNode = loop.getHeader().getBeginNode();
 430                 OptionValues options = beginNode.getOptions();
 431                 if (loopKilledLocations.visits() > ReadEliminationMaxLoopVisits.getValue(options)) {
 432                     // we have processed the loop too many times, kill all locations so the inner
 433                     // loop will never be processed more than once again on visit
 434                     loopKilledLocations.setKillsAll();
 435                 } else {
 436                     // we have fully processed this loop >1 times, update the killed locations
 437                     EconomicSet<LocationIdentity> forwardEndLiveLocations = EconomicSet.create(Equivalence.DEFAULT);
 438                     for (ReadCacheEntry entry : initialState.readCache.getKeys()) {
 439                         forwardEndLiveLocations.add(entry.identity);
 440                     }
 441                     for (ReadCacheEntry entry : mergedStates.readCache.getKeys()) {
 442                         forwardEndLiveLocations.remove(entry.identity);
 443                     }
 444                     // every location that is alive before the loop but not after is killed by the
 445                     // loop
 446                     for (LocationIdentity location : forwardEndLiveLocations) {
 447                         loopKilledLocations.rememberLoopKilledLocation(location);
 448                     }
 449                     if (debug.isLogEnabled() && loopKilledLocations != null) {
 450                         debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s",
 451                                         beginNode, forwardEndLiveLocations);
 452                     }
 453                 }
 454                 // remember the loop visit
 455                 loopKilledLocations.visited();
 456             }
 457         }
 458     }
 459 
 460     @Override
 461     protected PEReadEliminationBlockState stripKilledLoopLocations(Loop<Block> loop, PEReadEliminationBlockState originalInitialState) {
 462         PEReadEliminationBlockState initialState = super.stripKilledLoopLocations(loop, originalInitialState);
 463         LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop);
 464         if (loopKilledLocations != null && loopKilledLocations.loopKillsLocations()) {
 465             Iterator<ReadCacheEntry> it = initialState.readCache.getKeys().iterator();
 466             while (it.hasNext()) {
 467                 ReadCacheEntry entry = it.next();
 468                 if (loopKilledLocations.containsLocation(entry.identity)) {
 469                     it.remove();
 470                 }
 471             }
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File