6565import jdk .graal .compiler .nodeinfo .InputType ;
6666import jdk .graal .compiler .nodeinfo .NodeInfo ;
6767import jdk .graal .compiler .nodes .GraphDecoder .MethodScope ;
68- import jdk .graal .compiler .nodes .GraphDecoder .ProxyPlaceholder ;
6968import jdk .graal .compiler .nodes .calc .FloatingNode ;
7069import jdk .graal .compiler .nodes .extended .IntegerSwitchNode ;
7170import jdk .graal .compiler .nodes .extended .SwitchNode ;
@@ -420,7 +419,7 @@ protected LoopExplosionState(FrameState state, MergeNode merge) {
420419 if (value == null ) {
421420 h = h * 31 + 1234 ;
422421 } else {
423- h = h * 31 + ProxyPlaceholder . unwrap ( value ) .hashCode ();
422+ h = h * 31 + value .hashCode ();
424423 }
425424 }
426425 this .hashCode = h ;
@@ -436,11 +435,18 @@ public boolean equals(Object obj) {
436435 FrameState thisState = state ;
437436 assert thisState .outerFrameState () == otherState .outerFrameState () : Assertions .errorMessage (thisState , thisState .outerFrameState (), otherState , otherState .outerFrameState ());
438437
439- Iterator <ValueNode > thisIter = thisState .values ().iterator ();
440- Iterator <ValueNode > otherIter = otherState .values ().iterator ();
441- while (thisIter .hasNext () && otherIter .hasNext ()) {
442- ValueNode thisValue = ProxyPlaceholder .unwrap (thisIter .next ());
443- ValueNode otherValue = ProxyPlaceholder .unwrap (otherIter .next ());
438+ final NodeInputList <ValueNode > thisValues = thisState .values ();
439+ final NodeInputList <ValueNode > otherValues = otherState .values ();
440+
441+ final int size = thisValues .size ();
442+ if (size != otherValues .size ()) {
443+ return false ;
444+ }
445+
446+ for (int i = 0 ; i < size ; i ++) {
447+ final ValueNode thisValue = thisValues .get (i );
448+ final ValueNode otherValue = otherValues .get (i );
449+
444450 if (thisValue != otherValue ) {
445451 return false ;
446452 }
@@ -502,49 +508,6 @@ public InvokeData(Invoke invoke, ResolvedJavaType contextType, int invokeOrderId
502508 }
503509 }
504510
505- /**
506- * A node that is created during
507- * {@link jdk.graal.compiler.nodes.graphbuilderconf.LoopExplosionPlugin.LoopExplosionKind#MERGE_EXPLODE
508- * loop explosion} that can later be replaced by a ProxyNode if {@link LoopDetector loop
509- * detection} finds out that the value is defined in the loop, but used outside the loop.
510- */
511- @ NodeInfo (cycles = CYCLES_IGNORED , size = SIZE_IGNORED )
512- protected static final class ProxyPlaceholder extends FloatingNode implements Canonicalizable {
513- public static final NodeClass <ProxyPlaceholder > TYPE = NodeClass .create (ProxyPlaceholder .class );
514-
515- @ Input ValueNode value ;
516- @ Input (InputType .Association ) Node proxyPoint ;
517-
518- public ProxyPlaceholder (ValueNode value , MergeNode proxyPoint ) {
519- super (TYPE , value .stamp (NodeView .DEFAULT ));
520- this .value = value ;
521- this .proxyPoint = proxyPoint ;
522- }
523-
524- void setValue (ValueNode value ) {
525- updateUsages (this .value , value );
526- this .value = value ;
527- }
528-
529- @ Override
530- public Node canonical (CanonicalizerTool tool ) {
531- if (tool .allUsagesAvailable ()) {
532- /* The node is always unnecessary after graph decoding. */
533- return value ;
534- } else {
535- return this ;
536- }
537- }
538-
539- public static ValueNode unwrap (ValueNode value ) {
540- ValueNode result = value ;
541- while (result instanceof ProxyPlaceholder ) {
542- result = ((ProxyPlaceholder ) result ).value ;
543- }
544- return result ;
545- }
546- }
547-
548511 private static final TimerKey MakeSuccessorStubsTimer = DebugContext .timer ("PartialEvaluation-MakeSuccessorStubs" ).doc ("Time spent in making successor stubs for the PE." );
549512 private static final TimerKey ReadPropertiesTimer = DebugContext .timer ("PartialEvaluation-ReadProperties" ).doc ("Time spent in reading node properties in the PE." );
550513
@@ -1042,6 +1005,11 @@ protected void handleLoopExplosionBegin(MethodScope methodScope, LoopScope loopS
10421005 }
10431006 }
10441007
1008+ /*
1009+ * Merge explosion: When doing merge-explode PE loops are detected after partial evaluation
1010+ * in a dedicated steps. Therefore, we create merge nodes instead of loop begins and loop
1011+ * exits and later replace them with the detected loop begin and loop exit nodes.
1012+ */
10451013 MergeNode merge = graph .add (new MergeNode ());
10461014 methodScope .loopExplosionMerges .add (merge );
10471015
@@ -1053,65 +1021,6 @@ protected void handleLoopExplosionBegin(MethodScope methodScope, LoopScope loopS
10531021 }
10541022 methodScope .loopExplosionHead = merge ;
10551023 }
1056-
1057- /*
1058- * Proxy generation and merge explosion: When doing merge-explode PE loops are detected
1059- * after partial evaluation in a dedicated steps. Therefore, we create merge nodes
1060- * instead of loop begins and loop exits and later replace them with the detected loop
1061- * begin and loop exit nodes.
1062- *
1063- * However, in order to create the correct loop proxies, all values alive at a merge
1064- * created for a loop begin/loop exit replacement merge, we create so called proxy
1065- * placeholder nodes. These nodes are attached to a merge and proxy the corresponding
1066- * node. Later, when we replace a merge with a loop exit, we visit all live nodes at
1067- * that loop exit and replace the proxy placeholders with real value proxy nodes.
1068- *
1069- * Since we cannot (this would explode immediately) proxy all nodes for every merge
1070- * during explosion, we only create nodes at the loop explosion begins for nodes that
1071- * are alive at the framestate of the respective loop begin. This is fine as long as all
1072- * values proxied out of a loop are alive at the loop header. However, this is not true
1073- * for all values (imagine do-while loops). Thus, we may create, in very specific
1074- * patterns, unschedulable graphs since we miss the creation of proxy nodes.
1075- *
1076- * There is currently no straight forward solution to this problem, thus we shift the
1077- * work to the implementor side where such patterns can typically be easily fixed by
1078- * creating loop phis and assigning them correctly.
1079- */
1080- FrameState .ValueFunction valueFunction = new FrameState .ValueFunction () {
1081-
1082- @ Override
1083- public ValueNode apply (int index , ValueNode frameStateValue ) {
1084- if (frameStateValue == null || frameStateValue .isConstant () || !graph .isNew (methodScope .methodStartMark , frameStateValue )) {
1085- return frameStateValue ;
1086-
1087- } else {
1088- ProxyPlaceholder newFrameStateValue = graph .unique (new ProxyPlaceholder (frameStateValue , merge ));
1089-
1090- /*
1091- * We do not have the orderID of the value anymore, so we need to search
1092- * through the complete list of nodes to find a match.
1093- */
1094- for (int i = 0 ; i < loopScope .createdNodes .length ; i ++) {
1095- if (loopScope .createdNodes [i ] == frameStateValue ) {
1096- loopScope .createdNodes [i ] = newFrameStateValue ;
1097- }
1098- }
1099-
1100- if (loopScope .initialCreatedNodes != null ) {
1101- for (int i = 0 ; i < loopScope .initialCreatedNodes .length ; i ++) {
1102- if (loopScope .initialCreatedNodes [i ] == frameStateValue ) {
1103- loopScope .initialCreatedNodes [i ] = newFrameStateValue ;
1104- }
1105- }
1106- }
1107- return newFrameStateValue ;
1108- }
1109- }
1110- };
1111- FrameState newFrameState = graph .add (frameState .duplicate (valueFunction ));
1112-
1113- frameState .replaceAtUsagesAndDelete (newFrameState );
1114- frameState = newFrameState ;
11151024 }
11161025
11171026 loopBegin .replaceAtUsagesAndDelete (merge );
@@ -1192,7 +1101,7 @@ protected void handleFixedNode(MethodScope methodScope, LoopScope loopScope, int
11921101 * Hook for subclasses for early canonicalization of IfNodes and IntegerSwitchNodes.
11931102 *
11941103 * "Early" means that this is called before successor stubs creation. Therefore, all successors
1195- * are null a this point, and calling any method using them without prior manual initialization
1104+ * are null at this point, and calling any method using them without prior manual initialization
11961105 * will fail.
11971106 *
11981107 * @param methodScope The current method.
@@ -1303,9 +1212,6 @@ protected void handleLoopExplosionProxyNodes(MethodScope methodScope, LoopScope
13031212 ValueNode phiInput = proxy .value ();
13041213
13051214 if (loopExitPlaceholder != null ) {
1306- if (!phiInput .isConstant ()) {
1307- phiInput = graph .unique (new ProxyPlaceholder (phiInput , loopExitPlaceholder ));
1308- }
13091215 registerNode (loopScope , proxyOrderId , phiInput , true , false );
13101216 }
13111217
@@ -1776,6 +1682,7 @@ protected void registerNode(LoopScope loopScope, int nodeOrderId, Node node, boo
17761682 assert node == null || node .isAlive ();
17771683 assert allowNull || node != null ;
17781684 assert allowOverwrite || lookupNode (loopScope , nodeOrderId ) == null ;
1685+
17791686 loopScope .createdNodes [nodeOrderId ] = node ;
17801687 if (loopScope .methodScope .inliningLogDecoder != null ) {
17811688 loopScope .methodScope .inliningLogDecoder .registerNode (loopScope .methodScope .inliningLog , node , nodeOrderId );
@@ -1804,11 +1711,6 @@ protected Object readObject(MethodScope methodScope) {
18041711 * @param methodScope The current method.
18051712 */
18061713 protected void cleanupGraph (MethodScope methodScope ) {
1807- for (MergeNode merge : graph .getNodes (MergeNode .TYPE )) {
1808- for (ProxyPlaceholder placeholder : merge .usages ().filter (ProxyPlaceholder .class ).snapshot ()) {
1809- placeholder .replaceAndDelete (placeholder .value );
1810- }
1811- }
18121714 assert verifyEdges ();
18131715 }
18141716
@@ -2271,70 +2173,24 @@ private void insertLoopNodes(Loop loop) {
22712173
22722174 /**
22732175 * During graph decoding, we create a FrameState for every exploded loop iteration. This is
2274- * mostly the state that we want, we only need to tweak it a little bit: we need to insert the
2275- * appropriate ProxyNodes for all values that are created inside the loop and that flow out of
2276- * the loop.
2176+ * mostly the state that we want, we only need to tweak it a little bit to account for phis.
22772177 */
22782178 private void assignLoopExitState (LoopExitNode loopExit , AbstractMergeNode loopExplosionMerge , AbstractEndNode loopExplosionEnd ) {
22792179 FrameState oldState = loopExplosionMerge .stateAfter ();
22802180
2281- /* Collect all nodes that are in the FrameState at the LoopBegin. */
2282- EconomicSet <Node > loopBeginValues = EconomicSet .create (Equivalence .IDENTITY );
2283- for (FrameState state = loopExit .loopBegin ().stateAfter (); state != null ; state = state .outerFrameState ()) {
2284- for (ValueNode value : state .values ()) {
2285- if (value != null && !value .isConstant () && !loopExit .loopBegin ().isPhiAtMerge (value )) {
2286- loopBeginValues .add (ProxyPlaceholder .unwrap (value ));
2287- }
2288- }
2289- }
2290-
2291- /* The framestate may contain a value multiple times */
2292- EconomicMap <ValueNode , ValueNode > old2NewValues = EconomicMap .create ();
22932181 FrameState .ValueFunction valueFunction = new FrameState .ValueFunction () {
2294-
22952182 @ Override
2296- public ValueNode apply (int index , ValueNode v ) {
2297- if (v != null && old2NewValues .containsKey (v )) {
2298- return old2NewValues .get (v );
2299- }
2300-
2301- ValueNode value = v ;
2302- ValueNode realValue = ProxyPlaceholder .unwrap (value );
2303-
2183+ public ValueNode apply (int index , ValueNode value ) {
23042184 /*
23052185 * The LoopExit is inserted before the existing merge, i.e., separately for every
23062186 * branch that leads to the merge. So for phi functions of the merge, we need to
23072187 * take the input that corresponds to our branch.
23082188 */
2309- if (realValue instanceof PhiNode && loopExplosionMerge .isPhiAtMerge (realValue )) {
2310- value = ((PhiNode ) realValue ).valueAt (loopExplosionEnd );
2311- realValue = ProxyPlaceholder .unwrap (value );
2312- }
2313-
2314- if (realValue == null || realValue .isConstant () || loopBeginValues .contains (realValue ) || !graph .isNew (methodScope .methodStartMark , realValue )) {
2315- /*
2316- * value v, input to the old state, can already be a proxy placeholder node to
2317- * another, dominating loop exit, we must not take the unwrapped value in this
2318- * case but the properly proxied one
2319- */
2320- if (v != null ) {
2321- old2NewValues .put (v , v );
2322- }
2323- return v ;
2324- } else {
2325- /*
2326- * The node is not in the FrameState of the LoopBegin, i.e., it is a value
2327- * computed inside the loop.
2328- */
2329- GraalError .guarantee (value instanceof ProxyPlaceholder && ((ProxyPlaceholder ) value ).proxyPoint == loopExplosionMerge ,
2330- "Value flowing out of loop, but we are not prepared to insert a ProxyNode" );
2331-
2332- ProxyPlaceholder proxyPlaceholder = (ProxyPlaceholder ) value ;
2333- ValueProxyNode proxy = ProxyNode .forValue (proxyPlaceholder .value , loopExit );
2334- proxyPlaceholder .setValue (proxy );
2335- old2NewValues .put (v , proxy );
2336- return proxy ;
2189+ if (loopExplosionMerge .isPhiAtMerge (value )) {
2190+ assert value instanceof PhiNode : "isPhiAtMerge should guarantee that value is a PhiNode" ;
2191+ return ((PhiNode ) value ).valueAt (loopExplosionEnd );
23372192 }
2193+ return value ;
23382194 }
23392195 };
23402196
@@ -2344,6 +2200,12 @@ public ValueNode apply(int index, ValueNode v) {
23442200 loopExit .setStateAfter (graph .add (newState ));
23452201 }
23462202
2203+ FrameState newState = oldState .duplicate (valueFunction );
2204+
2205+ assert loopExit .stateAfter () == null ;
2206+ loopExit .setStateAfter (graph .add (newState ));
2207+ }
2208+
23472209 /**
23482210 * Graal does not support irreducible loops (loops with more than one entry point). There are
23492211 * two ways to make them reducible: 1) duplicate nodes (peel a loop iteration starting at the
@@ -2389,7 +2251,7 @@ private void handleIrreducibleLoop(Loop loop) {
23892251 ValueNode curLoopValue = loopValues .get (i );
23902252 ValueNode curExplosionHeadValue = explosionHeadValues .get (i );
23912253
2392- if (ProxyPlaceholder . unwrap ( curLoopValue ) != ProxyPlaceholder . unwrap ( curExplosionHeadValue ) ) {
2254+ if (curLoopValue != curExplosionHeadValue ) {
23932255 if (loopVariableIndex != -1 ) {
23942256 throw bailout ("must have only one variable that is changed in loop. " + loopValue + " != " + explosionHeadValue + " and " + curLoopValue + " != " + curExplosionHeadValue );
23952257 }
0 commit comments