a better workscheduler--still has a deficiency because it does not dynamically create...
[IRC.git] / Robust / src / Analysis / MLP / MLPAnalysis.java
index b658a2e5ad2d7623bf65a009064f38ef253853ba..4fa426014d619d5291e4e91db8884914c047a3f2 100644 (file)
@@ -27,7 +27,9 @@ public class MLPAnalysis {
   private Hashtable< FlatNode, Set<TempDescriptor>      > notAvailableResults;
   private Hashtable< FlatNode, CodePlan                 > codePlans;
 
-  private static int maxSESEage = -1;
+  private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
+
+  public static int maxSESEage = -1;
 
 
   // use these methods in BuildCode to have access to analysis results
@@ -73,6 +75,9 @@ public class MLPAnalysis {
     notAvailableResults  = new Hashtable< FlatNode, Set<TempDescriptor>      >();
     codePlans            = new Hashtable< FlatNode, CodePlan                 >();
 
+    wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
+
+
     FlatMethod fmMain = state.getMethodFlat( tu.getMain() );
 
     rootSESE = (FlatSESEEnterNode) fmMain.getNext(0);    
@@ -80,6 +85,9 @@ public class MLPAnalysis {
     rootSESE.setmdEnclosing( fmMain.getMethod() );
     rootSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
 
+    if( state.MLPDEBUG ) {      
+      System.out.println( "" );
+    }
 
     // 1st pass
     // run analysis on each method that is actually called
@@ -93,6 +101,9 @@ public class MLPAnalysis {
       // and organize them into roots and children
       buildForestForward( fm );
     }
+    if( state.MLPDEBUG ) {      
+      //System.out.println( "\nSESE Hierarchy\n--------------\n" ); printSESEHierarchy();
+    }
 
 
     // 2nd pass, results are saved in FlatSESEEnterNode, so
@@ -115,6 +126,10 @@ public class MLPAnalysis {
     // 4th pass, compute liveness contribution from
     // virtual reads discovered in variable pass
     livenessAnalysisBackward( rootSESE, true, null, fmMain.getFlatExit() );        
+    if( state.MLPDEBUG ) {      
+      //System.out.println( "\nLive-In, SESE View\n-------------\n" ); printSESELiveness();
+      //System.out.println( "\nLive-In, Root View\n------------------\n"+fmMain.printMethod( livenessRootView ) );
+    }
 
 
     // 5th pass
@@ -123,13 +138,31 @@ public class MLPAnalysis {
       Descriptor d  = methItr.next();      
       FlatMethod fm = state.getMethodFlat( d );
 
+      // prune variable results in one traversal
+      // by removing reference variables that are not live
+      pruneVariableResultsWithLiveness( fm );
+    }
+    if( state.MLPDEBUG ) {      
+      //System.out.println( "\nVariable Results-Out\n----------------\n"+fmMain.printMethod( variableResults ) );
+    }
+    
+
+    // 6th pass
+    methItr = ownAnalysis.descriptorsToAnalyze.iterator();
+    while( methItr.hasNext() ) {
+      Descriptor d  = methItr.next();      
+      FlatMethod fm = state.getMethodFlat( d );
+
       // compute what is not available at every program
       // point, in a forward fixed-point pass
       notAvailableForward( fm );
     }
+    if( state.MLPDEBUG ) {      
+      //System.out.println( "\nNot Available Results-Out\n---------------------\n"+fmMain.printMethod( notAvailableResults ) );
+    }
 
 
-    // 5th pass
+    // 7th pass
     methItr = ownAnalysis.descriptorsToAnalyze.iterator();
     while( methItr.hasNext() ) {
       Descriptor d  = methItr.next();      
@@ -138,18 +171,23 @@ public class MLPAnalysis {
       // compute a plan for code injections
       computeStallsForward( fm );
     }
-
-
-    if( state.MLPDEBUG ) {      
-      System.out.println( "" );
-      //System.out.println( "\nSESE Hierarchy\n--------------\n" ); printSESEHierarchy();
-      System.out.println( "\nSESE Liveness\n-------------\n" ); printSESELiveness();
-      //System.out.println( "\nLiveness Root View\n------------------\n"+fmMain.printMethod( livenessRootView ) );
-      //System.out.println( "\nVariable Results\n----------------\n"+fmMain.printMethod( variableResults ) );
-      //System.out.println( "\nNot Available Results\n---------------------\n"+fmMain.printMethod( notAvailableResults ) );
+    if( state.MLPDEBUG ) {
       //System.out.println( "\nCode Plans\n----------\n"+fmMain.printMethod( codePlans ) );
     }
 
+    // splice new IR nodes into graph after all
+    // analysis passes are complete
+    Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
+    while( spliceItr.hasNext() ) {
+      Map.Entry               me    = (Map.Entry)               spliceItr.next();
+      FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
+      fwdvn.spliceIntoIR();
+    }
+
+    // detailed per-SESE information
+    if( state.MLPDEBUG ) {
+      System.out.println( "\nSESE info\n-------------\n" ); printSESEInfo();
+    }
 
     double timeEndAnalysis = (double) System.nanoTime();
     double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
@@ -412,6 +450,49 @@ public class MLPAnalysis {
     }
   }
 
+  private void printSESEInfo() {
+    printSESEInfoTree( rootSESE );
+    System.out.println( "" );
+  }
+
+  private void printSESEInfoTree( FlatSESEEnterNode fsen ) {
+
+    System.out.println( "SESE "+fsen.getPrettyIdentifier()+" {" );
+
+    System.out.println( "  in-set: "+fsen.getInVarSet() );
+    Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
+    while( tItr.hasNext() ) {
+      TempDescriptor inVar = tItr.next();
+      if( fsen.getReadyInVarSet().contains( inVar ) ) {
+       System.out.println( "    (ready)  "+inVar );
+      }
+      if( fsen.getStaticInVarSet().contains( inVar ) ) {
+       System.out.println( "    (static) "+inVar );
+      } 
+      if( fsen.getDynamicInVarSet().contains( inVar ) ) {
+       System.out.println( "    (dynamic)"+inVar );
+      }
+    }
+
+    System.out.println( "  out-set: "+fsen.getOutVarSet() );
+
+    /*
+    System.out.println( "  static names to track:" );
+    tItr = fsen.getOutVarSet().iterator();
+    while( tItr.hasNext() ) {
+      System.out.println( "    "+tItr.next() );
+    }
+    */
+
+    System.out.println( "}" );
+
+    Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
+    while( childItr.hasNext() ) {
+      FlatSESEEnterNode fsenChild = childItr.next();
+      printSESEInfoTree( fsenChild );
+    }
+  }
+
 
   private void variableAnalysisForward( FlatMethod fm ) {
 
@@ -459,8 +540,12 @@ public class MLPAnalysis {
     case FKind.FlatSESEEnterNode: {
       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
       assert fsen.equals( currentSESE );
+
       vstTable.age( currentSESE );
       vstTable.assertConsistency();
+
+      vstTable.ownInSet( currentSESE );
+      vstTable.assertConsistency();
     } break;
 
     case FKind.FlatSESEExitNode: {
@@ -477,6 +562,25 @@ public class MLPAnalysis {
       }
       livenessVirtualReads.put( fn, virLiveIn );
       vstTable.assertConsistency();
+
+      // then all child out-set tokens are guaranteed
+      // to be filled in, so clobber those entries with
+      // the latest, clean sources
+      Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
+      while( outVarItr.hasNext() ) {
+        TempDescriptor outVar = outVarItr.next();
+        HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
+        ts.add( outVar );
+        VariableSourceToken vst = new VariableSourceToken( ts,
+                                                           fsen,
+                                                           new Integer( 0 ),
+                                                           outVar
+                                                           );
+        vstTable.remove( outVar );
+        vstTable.add( vst );
+      }
+      vstTable.assertConsistency();
+
     } break;
 
     case FKind.FlatOpNode: {
@@ -484,7 +588,7 @@ public class MLPAnalysis {
 
       if( fon.getOp().getOp() == Operation.ASSIGN ) {
        TempDescriptor lhs = fon.getDest();
-       TempDescriptor rhs = fon.getLeft();
+       TempDescriptor rhs = fon.getLeft();        
 
        vstTable.remove( lhs );
 
@@ -497,25 +601,12 @@ public class MLPAnalysis {
           HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
           ts.add( lhs );
 
-          // if this is from a child, keep the source information
-          if( currentSESE.getChildren().contains( vst.getSESE() ) ) {    
-            forAddition.add( new VariableSourceToken( ts,
-                                                      vst.getSESE(),
-                                                      vst.getAge(),
-                                                      vst.getAddrVar()
-                                                      )
-                             );
-
-          // otherwise, it's our or an ancestor's token so we
-          // can assume we have everything we need
-          } else {
-            forAddition.add( new VariableSourceToken( ts,
-                                                      currentSESE,
-                                                      new Integer( 0 ),
-                                                      lhs
-                                                      )
-                             );
-          }
+          forAddition.add( new VariableSourceToken( ts,
+                                                    vst.getSESE(),
+                                                    vst.getAge(),
+                                                    vst.getAddrVar()
+                                                    )
+                           );
        }
 
         vstTable.addAll( forAddition );
@@ -565,6 +656,39 @@ public class MLPAnalysis {
   }
 
 
+  private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
+    
+    // start from flat method top, visit every node in
+    // method exactly once
+    Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
+    flatNodesToVisit.add( fm );
+
+    Set<FlatNode> visited = new HashSet<FlatNode>();    
+
+    while( !flatNodesToVisit.isEmpty() ) {
+      Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
+      FlatNode fn = fnItr.next();
+
+      flatNodesToVisit.remove( fn );
+      visited.add( fn );      
+
+      Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
+      VarSrcTokTable      vstTable    = variableResults.get( fn );
+      
+      // fix later, not working, only wanted it to make tables easier to read
+      //vstTable.pruneByLiveness( rootLiveSet );
+      
+      for( int i = 0; i < fn.numNext(); i++ ) {
+       FlatNode nn = fn.getNext( i );
+
+       if( !visited.contains( nn ) ) {
+         flatNodesToVisit.add( nn );
+       }
+      }
+    }
+  }
+
+
   private void notAvailableForward( FlatMethod fm ) {
 
     Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
@@ -587,7 +711,7 @@ public class MLPAnalysis {
           curr.addAll( notAvailIn );
         }
       }
-
+      
       if( !seseStack.empty() ) {
        notAvailable_nodeActions( fn, curr, seseStack.peek() );     
       }
@@ -628,28 +752,7 @@ public class MLPAnalysis {
       Set<TempDescriptor> liveTemps = livenessRootView.get( fn );
       assert liveTemps != null;
 
-      VarSrcTokTable vstTable = variableResults.get( fn );
-      assert vstTable != null;
-
-      Set<TempDescriptor> notAvailAtEnter = notAvailableResults.get( fsen );
-      assert notAvailAtEnter != null;
-
-      Iterator<TempDescriptor> tdItr = liveTemps.iterator();
-      while( tdItr.hasNext() ) {
-       TempDescriptor td = tdItr.next();
-
-       if( vstTable.get( fsen, td ).size() > 0 ) {
-         // there is at least one child token for this variable
-         notAvailSet.add( td );
-         continue;
-       }
-
-       if( notAvailAtEnter.contains( td ) ) {
-         // wasn't available at enter, not available now
-         notAvailSet.add( td );
-         continue;
-       }
-      }
+      notAvailSet.addAll( liveTemps );
     } break;
 
     case FKind.FlatOpNode: {
@@ -685,20 +788,41 @@ public class MLPAnalysis {
         TempDescriptor rTemp = readTemps[i];
         notAvailSet.remove( rTemp );
 
-       // if this variable has exactly one source, mark everything
-       // else from that source as available as well
-       VarSrcTokTable table = variableResults.get( fn );
-       Set<VariableSourceToken> srcs = table.get( rTemp );
+       // if this variable has exactly one source, potentially
+       // get other things from this source as well
+       VarSrcTokTable vstTable = variableResults.get( fn );
 
-       if( srcs.size() == 1 ) {
-         VariableSourceToken vst = srcs.iterator().next();
-         
-         Iterator<VariableSourceToken> availItr = table.get( vst.getSESE(), 
-                                                             vst.getAge()
-                                                           ).iterator();
+       Integer srcType = 
+         vstTable.getRefVarSrcType( rTemp, 
+                                    currentSESE,
+                                    currentSESE.getParent() );
+
+       if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
+
+         VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
+
+         Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
+                                                                vst.getAge()
+                                                                ).iterator();
+
+         // look through things that are also available from same source
          while( availItr.hasNext() ) {
            VariableSourceToken vstAlsoAvail = availItr.next();
-           notAvailSet.removeAll( vstAlsoAvail.getRefVars() );
+         
+           Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
+           while( refVarItr.hasNext() ) {
+             TempDescriptor refVarAlso = refVarItr.next();
+
+             // if a variable is available from the same source, AND it ALSO
+             // only comes from one statically known source, mark it available
+             Integer srcTypeAlso = 
+               vstTable.getRefVarSrcType( refVarAlso, 
+                                          currentSESE,
+                                          currentSESE.getParent() );
+             if( srcTypeAlso.equals( VarSrcTokTable.SrcType_STATIC ) ) {
+               notAvailSet.remove( refVarAlso );
+             }
+           }
          }
        }
       }
@@ -745,8 +869,15 @@ public class MLPAnalysis {
         }
       }
 
+      Set<TempDescriptor> dotSTlive = livenessRootView.get( fn );
+
       if( !seseStack.empty() ) {
-       computeStalls_nodeActions( fn, dotSTtable, dotSTnotAvailSet, seseStack.peek() );
+       computeStalls_nodeActions( fn, 
+                                  dotSTlive,
+                                  dotSTtable,
+                                  dotSTnotAvailSet,
+                                  seseStack.peek()
+                                  );
       }
 
       for( int i = 0; i < fn.numNext(); i++ ) {
@@ -760,16 +891,50 @@ public class MLPAnalysis {
   }
 
   private void computeStalls_nodeActions( FlatNode fn,
-                                          VarSrcTokTable vstTable,
-                                         Set<TempDescriptor> notAvailSet,
+                                         Set<TempDescriptor> liveSetIn,
+                                          VarSrcTokTable vstTableIn,
+                                         Set<TempDescriptor> notAvailSetIn,
                                           FlatSESEEnterNode currentSESE ) {
-    CodePlan plan = new CodePlan();
 
+    CodePlan plan = new CodePlan( currentSESE);
 
     switch( fn.kind() ) {
 
     case FKind.FlatSESEEnterNode: {
       FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
+
+      // track the source types of the in-var set so generated
+      // code at this SESE issue can compute the number of
+      // dependencies properly
+      Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
+      while( inVarItr.hasNext() ) {
+       TempDescriptor inVar = inVarItr.next();
+       Integer srcType = 
+         vstTableIn.getRefVarSrcType( inVar, 
+                                      fsen,
+                                      fsen.getParent() );
+
+       // the current SESE needs a local space to track the dynamic
+       // variable and the child needs space in its SESE record
+       if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
+         fsen.addDynamicInVar( inVar );
+         fsen.getParent().addDynamicVar( inVar );
+
+       } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
+         fsen.addStaticInVar( inVar );
+         VariableSourceToken vst = vstTableIn.get( inVar ).iterator().next();
+         fsen.putStaticInVar2src( inVar, vst );
+         fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(), 
+                                                     vst.getAge() 
+                                                   ) 
+                               );
+
+       } else {
+         assert srcType.equals( VarSrcTokTable.SrcType_READY );
+         fsen.addReadyInVar( inVar );
+       }       
+      }
+
     } break;
 
     case FKind.FlatSESEExitNode: {
@@ -780,9 +945,26 @@ public class MLPAnalysis {
       FlatOpNode fon = (FlatOpNode) fn;
 
       if( fon.getOp().getOp() == Operation.ASSIGN ) {
+       TempDescriptor lhs = fon.getDest();
+       TempDescriptor rhs = fon.getLeft();        
+
        // if this is an op node, don't stall, copy
        // source and delay until we need to use value
 
+       // but check the source type of rhs variable
+       // and if dynamic, lhs becomes dynamic, too,
+       // and we need to keep dynamic sources during
+       Integer srcType 
+         = vstTableIn.getRefVarSrcType( rhs,
+                                        currentSESE,
+                                        currentSESE.getParent() );
+
+       if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
+         plan.addDynAssign( lhs, rhs );
+         currentSESE.addDynamicVar( lhs );
+         currentSESE.addDynamicVar( rhs );
+       }
+
        // only break if this is an ASSIGN op node,
        // otherwise fall through to default case
        break;
@@ -792,12 +974,9 @@ public class MLPAnalysis {
     // note that FlatOpNode's that aren't ASSIGN
     // fall through to this default case
     default: {          
-      // decide if we must stall for variables dereferenced at this node
-      Set<VariableSourceToken> stallSet = vstTable.getStallSet( currentSESE );
 
       // a node with no live set has nothing to stall for
-      Set<TempDescriptor> liveSet = livenessRootView.get( fn );
-      if( liveSet == null ) {
+      if( liveSetIn == null ) {
        break;
       }
 
@@ -807,63 +986,59 @@ public class MLPAnalysis {
 
        // ignore temps that are definitely available 
        // when considering to stall on it
-       if( !notAvailSet.contains( readtmp ) ) {
+       if( !notAvailSetIn.contains( readtmp ) ) {
          continue;
        }
 
-       // Two cases:
-        Set<VariableSourceToken> srcs = vstTable.get( readtmp );
-       assert !srcs.isEmpty();
+       // check the source type of this variable
+       Integer srcType 
+         = vstTableIn.getRefVarSrcType( readtmp,
+                                      currentSESE,
+                                      currentSESE.getParent() );
 
-       // 1) Multiple token/age pairs or unknown age: Stall for
-       // dynamic name only.
-       if( srcs.size() > 1 || 
-           srcs.iterator().next().getAge() == maxSESEage ) {
-         
-         
+       if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
+         // 1) It is not clear statically where this variable will
+         // come from statically, so dynamically we must keep track
+         // along various control paths, and therefore when we stall,
+         // just stall for the exact thing we need and move on
+         plan.addDynamicStall( readtmp );
+         currentSESE.addDynamicVar( readtmp );
 
-       // 2) Single token/age pair: Stall for token/age pair, and copy
-       // all live variables with same token/age pair at the same
-       // time.  This is the same stuff that the notavaialable analysis 
-       // marks as now available.        
-       } else {          
-         VariableSourceToken vst = srcs.iterator().next();                       
+       } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {    
+         // 2) Single token/age pair: Stall for token/age pair, and copy
+         // all live variables with same token/age pair at the same
+         // time.  This is the same stuff that the notavaialable analysis 
+         // marks as now available.      
 
-         Iterator<VariableSourceToken> availItr = 
-           vstTable.get( vst.getSESE(), 
-                         vst.getAge()
-                       ).iterator();
-
-         System.out.println( "Considering a stall on "+vst+
-                             " and also getting\n    "+vstTable.get( vst.getSESE(), 
-                         vst.getAge()
-                                                                     ) );
+         VariableSourceToken vst = vstTableIn.get( readtmp ).iterator().next();
 
-         // only grab additional stuff that is live
-         Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
+         Iterator<VariableSourceToken> availItr = 
+           vstTableIn.get( vst.getSESE(), vst.getAge() ).iterator();
 
          while( availItr.hasNext() ) {
            VariableSourceToken vstAlsoAvail = availItr.next();
 
-           if( liveSet.contains( vstAlsoAvail.getAddrVar() ) ) {
-             copySet.add( vstAlsoAvail.getAddrVar() );
-           }
+           // only grab additional stuff that is live
+           Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
 
-           /*
            Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
            while( refVarItr.hasNext() ) {
              TempDescriptor refVar = refVarItr.next();
-             if( liveSet.contains( refVar ) ) {
+             if( liveSetIn.contains( refVar ) ) {
                copySet.add( refVar );
              }
            }
-           */
-         }
-         
 
-         SESEandAgePair stallPair = new SESEandAgePair( vst.getSESE(), vst.getAge() );   
-         plan.addStall2CopySet( stallPair, copySet );
-         System.out.println( "("+stallPair+"->"+copySet+")" );
+           if( !copySet.isEmpty() ) {
+             plan.addStall2CopySet( vstAlsoAvail, copySet );
+           }
+         }                      
+
+       } else {
+         // the other case for srcs is READY from a parent, however
+         // since we are only examining variables that come from
+         // children tokens, this should never occur
+         assert false;
        }
 
        // assert that everything being stalled for is in the
@@ -873,38 +1048,61 @@ public class MLPAnalysis {
 
       }      
     } break;
-
+      
     } // end switch
 
 
     // identify sese-age pairs that are statically useful
     // and should have an associated SESE variable in code
-    Set<VariableSourceToken> staticSet = vstTable.getStaticSet();
+    Set<VariableSourceToken> staticSet = vstTableIn.getStaticSet();
     Iterator<VariableSourceToken> vstItr = staticSet.iterator();
     while( vstItr.hasNext() ) {
       VariableSourceToken vst = vstItr.next();
       currentSESE.addNeededStaticName( 
         new SESEandAgePair( vst.getSESE(), vst.getAge() ) 
                                     );
+      currentSESE.mustTrackAtLeastAge( vst.getAge() );
     }
 
-    // if any variable at this node has a static source (exactly one sese)
-    // but goes to a dynamic source at a next node, write its dynamic addr      
-    Set<VariableSourceToken> static2dynamicSet = new HashSet<VariableSourceToken>();
+
+    codePlans.put( fn, plan );
+
+
+    // if any variables at this-node-*dot* have a static source (exactly one vst)
+    // but go to a dynamic source at next-node-*dot*, create a new IR graph
+    // node on that edge to track the sources dynamically
+    VarSrcTokTable thisVstTable = variableResults.get( fn );
     for( int i = 0; i < fn.numNext(); i++ ) {
-      FlatNode nn = fn.getNext( i );
-      VarSrcTokTable nextVstTable = variableResults.get( nn );
+      FlatNode            nn           = fn.getNext( i );
+      VarSrcTokTable      nextVstTable = variableResults.get( nn );
+      Set<TempDescriptor> nextLiveIn   = livenessRootView.get( nn );
+
       // the table can be null if it is one of the few IR nodes
       // completely outside of the root SESE scope
-      if( nextVstTable != null ) {
-       static2dynamicSet.addAll( vstTable.getStatic2DynamicSet( nextVstTable ) );
+      if( nextVstTable != null && nextLiveIn != null ) {
+
+       Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet = 
+         thisVstTable.getStatic2DynamicSet( nextVstTable, nextLiveIn );
+       
+       if( !static2dynamicSet.isEmpty() ) {
+
+         // either add these results to partial fixed-point result
+         // or make a new one if we haven't made any here yet
+         FlatEdge fe = new FlatEdge( fn, nn );
+         FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
+
+         if( fwdvn == null ) {
+           fwdvn = new FlatWriteDynamicVarNode( fn, 
+                                                nn,
+                                                static2dynamicSet,
+                                                currentSESE
+                                                );
+           wdvNodesToSpliceIn.put( fe, fwdvn );
+         } else {
+           fwdvn.addMoreVar2Src( static2dynamicSet );
+         }
+       }
       }
     }
-
-    if( !static2dynamicSet.isEmpty() ) {
-      plan.setWriteToDynamicSrc( static2dynamicSet );
-    }
-
-    codePlans.put( fn, plan );
   }
 }