3 import Analysis.CallGraph.*;
4 import Analysis.OwnershipAnalysis.*;
12 public class MLPAnalysis {
14 // data from the compiler
16 private TypeUtil typeUtil;
17 private CallGraph callGraph;
18 private OwnershipAnalysis ownAnalysis;
20 private FlatSESEEnterNode rootSESE;
21 private Set<FlatSESEEnterNode> allSESEs;
23 private Hashtable< FlatNode, Stack<FlatSESEEnterNode> > seseStacks;
24 private Hashtable< FlatNode, Set<TempDescriptor> > livenessRootView;
25 private Hashtable< FlatNode, Set<TempDescriptor> > livenessVirtualReads;
26 private Hashtable< FlatNode, VarSrcTokTable > variableResults;
27 private Hashtable< FlatNode, Set<TempDescriptor> > notAvailableResults;
28 private Hashtable< FlatNode, CodePlan > codePlans;
30 private Hashtable<FlatEdge, FlatWriteDynamicVarNode> wdvNodesToSpliceIn;
32 public static int maxSESEage = -1;
35 // use these methods in BuildCode to have access to analysis results
36 public FlatSESEEnterNode getRootSESE() {
40 public Set<FlatSESEEnterNode> getAllSESEs() {
44 public int getMaxSESEage() {
49 public CodePlan getCodePlan( FlatNode fn ) {
50 CodePlan cp = codePlans.get( fn );
55 public MLPAnalysis( State state,
58 OwnershipAnalysis ownAnalysis
61 double timeStartAnalysis = (double) System.nanoTime();
65 this.callGraph = callGraph;
66 this.ownAnalysis = ownAnalysis;
67 this.maxSESEage = state.MLP_MAXSESEAGE;
69 // initialize analysis data structures
70 allSESEs = new HashSet<FlatSESEEnterNode>();
72 seseStacks = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
73 livenessVirtualReads = new Hashtable< FlatNode, Set<TempDescriptor> >();
74 variableResults = new Hashtable< FlatNode, VarSrcTokTable >();
75 notAvailableResults = new Hashtable< FlatNode, Set<TempDescriptor> >();
76 codePlans = new Hashtable< FlatNode, CodePlan >();
78 wdvNodesToSpliceIn = new Hashtable<FlatEdge, FlatWriteDynamicVarNode>();
81 FlatMethod fmMain = state.getMethodFlat( tu.getMain() );
83 rootSESE = (FlatSESEEnterNode) fmMain.getNext(0);
84 rootSESE.setfmEnclosing( fmMain );
85 rootSESE.setmdEnclosing( fmMain.getMethod() );
86 rootSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
88 if( state.MLPDEBUG ) {
89 System.out.println( "" );
93 // run analysis on each method that is actually called
94 // reachability analysis already computed this so reuse
95 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
96 while( methItr.hasNext() ) {
97 Descriptor d = methItr.next();
98 FlatMethod fm = state.getMethodFlat( d );
100 // find every SESE from methods that may be called
101 // and organize them into roots and children
102 buildForestForward( fm );
104 if( state.MLPDEBUG ) {
105 //System.out.println( "\nSESE Hierarchy\n--------------\n" ); printSESEHierarchy();
109 // 2nd pass, results are saved in FlatSESEEnterNode, so
110 // intermediate results, for safety, are discarded
111 livenessAnalysisBackward( rootSESE, true, null, fmMain.getFlatExit() );
115 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
116 while( methItr.hasNext() ) {
117 Descriptor d = methItr.next();
118 FlatMethod fm = state.getMethodFlat( d );
120 // starting from roots do a forward, fixed-point
121 // variable analysis for refinement and stalls
122 variableAnalysisForward( fm );
126 // 4th pass, compute liveness contribution from
127 // virtual reads discovered in variable pass
128 livenessAnalysisBackward( rootSESE, true, null, fmMain.getFlatExit() );
129 if( state.MLPDEBUG ) {
130 //System.out.println( "\nLive-In, SESE View\n-------------\n" ); printSESELiveness();
131 //System.out.println( "\nLive-In, Root View\n------------------\n"+fmMain.printMethod( livenessRootView ) );
136 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
137 while( methItr.hasNext() ) {
138 Descriptor d = methItr.next();
139 FlatMethod fm = state.getMethodFlat( d );
141 // prune variable results in one traversal
142 // by removing reference variables that are not live
143 pruneVariableResultsWithLiveness( fm );
145 if( state.MLPDEBUG ) {
146 //System.out.println( "\nVariable Results-Out\n----------------\n"+fmMain.printMethod( variableResults ) );
151 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
152 while( methItr.hasNext() ) {
153 Descriptor d = methItr.next();
154 FlatMethod fm = state.getMethodFlat( d );
156 // compute what is not available at every program
157 // point, in a forward fixed-point pass
158 notAvailableForward( fm );
160 if( state.MLPDEBUG ) {
161 System.out.println( "\nNot Available Results-Out\n---------------------\n"+fmMain.printMethod( notAvailableResults ) );
166 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
167 while( methItr.hasNext() ) {
168 Descriptor d = methItr.next();
169 FlatMethod fm = state.getMethodFlat( d );
171 // compute a plan for code injections
172 computeStallsForward( fm );
174 if( state.MLPDEBUG ) {
175 System.out.println( "\nCode Plans\n----------\n"+fmMain.printMethod( codePlans ) );
179 // splice new IR nodes into graph after all
180 // analysis passes are complete
181 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
182 while( spliceItr.hasNext() ) {
183 Map.Entry me = (Map.Entry) spliceItr.next();
184 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
185 fwdvn.spliceIntoIR();
189 double timeEndAnalysis = (double) System.nanoTime();
190 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
191 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
192 System.out.println( treport );
196 private void buildForestForward( FlatMethod fm ) {
198 // start from flat method top, visit every node in
199 // method exactly once, find SESEs and remember
200 // roots and child relationships
201 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
202 flatNodesToVisit.add( fm );
204 Set<FlatNode> visited = new HashSet<FlatNode>();
206 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
207 seseStacks.put( fm, seseStackFirst );
209 while( !flatNodesToVisit.isEmpty() ) {
210 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
211 FlatNode fn = fnItr.next();
213 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
214 assert seseStack != null;
216 flatNodesToVisit.remove( fn );
219 buildForest_nodeActions( fn, seseStack, fm );
221 for( int i = 0; i < fn.numNext(); i++ ) {
222 FlatNode nn = fn.getNext( i );
224 if( !visited.contains( nn ) ) {
225 flatNodesToVisit.add( nn );
227 // clone stack and send along each analysis path
228 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
234 private void buildForest_nodeActions( FlatNode fn,
235 Stack<FlatSESEEnterNode> seseStack,
237 switch( fn.kind() ) {
239 case FKind.FlatSESEEnterNode: {
240 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
242 allSESEs.add( fsen );
243 fsen.setfmEnclosing( fm );
244 fsen.setmdEnclosing( fm.getMethod() );
245 fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
247 if( !seseStack.empty() ) {
248 seseStack.peek().addChild( fsen );
249 fsen.setParent( seseStack.peek() );
252 seseStack.push( fsen );
255 case FKind.FlatSESEExitNode: {
256 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
257 assert !seseStack.empty();
258 FlatSESEEnterNode fsen = seseStack.pop();
261 case FKind.FlatReturnNode: {
262 FlatReturnNode frn = (FlatReturnNode) fn;
263 if( !seseStack.empty() ) {
264 throw new Error( "Error: return statement enclosed within SESE "+
265 seseStack.peek().getPrettyIdentifier() );
272 private void printSESEHierarchy() {
273 // our forest is actually a tree now that
274 // there is an implicit root SESE
275 printSESEHierarchyTree( rootSESE, 0 );
276 System.out.println( "" );
279 private void printSESEHierarchyTree( FlatSESEEnterNode fsen, int depth ) {
280 for( int i = 0; i < depth; ++i ) {
281 System.out.print( " " );
283 System.out.println( "- "+fsen.getPrettyIdentifier() );
285 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
286 while( childItr.hasNext() ) {
287 FlatSESEEnterNode fsenChild = childItr.next();
288 printSESEHierarchyTree( fsenChild, depth + 1 );
293 private void livenessAnalysisBackward( FlatSESEEnterNode fsen,
295 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout,
298 // start from an SESE exit, visit nodes in reverse up to
299 // SESE enter in a fixed-point scheme, where children SESEs
300 // should already be analyzed and therefore can be skipped
301 // because child SESE enter node has all necessary info
302 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
304 FlatSESEExitNode fsexn = fsen.getFlatExit();
307 flatNodesToVisit.add( fexit );
309 flatNodesToVisit.add( fsexn );
310 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults=new Hashtable<FlatNode, Set<TempDescriptor>>();
313 liveout=new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
315 while( !flatNodesToVisit.isEmpty() ) {
316 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
317 flatNodesToVisit.remove( fn );
319 Set<TempDescriptor> prev = livenessResults.get( fn );
321 // merge sets from control flow joins
322 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
323 for( int i = 0; i < fn.numNext(); i++ ) {
324 FlatNode nn = fn.getNext( i );
325 Set<TempDescriptor> s = livenessResults.get( nn );
331 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
333 // if a new result, schedule backward nodes for analysis
334 if( !curr.equals( prev ) ) {
335 livenessResults.put( fn, curr );
337 // don't flow backwards past current SESE enter
338 if( !fn.equals( fsen ) ) {
339 for( int i = 0; i < fn.numPrev(); i++ ) {
340 FlatNode nn = fn.getPrev( i );
341 flatNodesToVisit.add( nn );
347 Set<TempDescriptor> s = livenessResults.get( fsen );
349 fsen.addInVarSet( s );
352 // remember liveness per node from the root view as the
353 // global liveness of variables for later passes to use
354 if( toplevel == true ) {
355 livenessRootView = livenessResults;
358 // post-order traversal, so do children first
359 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
360 while( childItr.hasNext() ) {
361 FlatSESEEnterNode fsenChild = childItr.next();
362 livenessAnalysisBackward( fsenChild, false, liveout, null );
366 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
367 Set<TempDescriptor> liveIn,
368 FlatSESEEnterNode currentSESE,
370 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
372 switch( fn.kind() ) {
374 case FKind.FlatSESEExitNode:
375 if (toplevel==true) {
376 FlatSESEExitNode exitn=(FlatSESEExitNode) fn;
377 //update liveout set for FlatSESEExitNode
378 if (!liveout.containsKey(exitn))
379 liveout.put(exitn, new HashSet<TempDescriptor>());
380 liveout.get(exitn).addAll(liveIn);
382 // no break, sese exits should also execute default actions
385 // handle effects of statement in reverse, writes then reads
386 TempDescriptor [] writeTemps = fn.writesTemps();
387 for( int i = 0; i < writeTemps.length; ++i ) {
388 liveIn.remove( writeTemps[i] );
391 FlatSESEExitNode exitnode=currentSESE.getFlatExit();
392 Set<TempDescriptor> livetemps=liveout.get(exitnode);
393 if (livetemps.contains(writeTemps[i])) {
394 //write to a live out temp...
395 //need to put in SESE liveout set
396 currentSESE.addOutVar(writeTemps[i]);
401 TempDescriptor [] readTemps = fn.readsTemps();
402 for( int i = 0; i < readTemps.length; ++i ) {
403 liveIn.add( readTemps[i] );
406 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
407 if( virtualReadTemps != null ) {
408 Iterator<TempDescriptor> vrItr = virtualReadTemps.iterator();
409 while( vrItr.hasNext() ) {
410 TempDescriptor vrt = vrItr.next();
421 private void printSESELiveness() {
422 // our forest is actually a tree now that
423 // there is an implicit root SESE
424 printSESELivenessTree( rootSESE );
425 System.out.println( "" );
428 private void printSESELivenessTree( FlatSESEEnterNode fsen ) {
430 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
431 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
432 while( tItr.hasNext() ) {
433 System.out.println( " "+tItr.next() );
435 System.out.println( "and out-set:" );
436 tItr = fsen.getOutVarSet().iterator();
437 while( tItr.hasNext() ) {
438 System.out.println( " "+tItr.next() );
440 System.out.println( "" );
443 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
444 while( childItr.hasNext() ) {
445 FlatSESEEnterNode fsenChild = childItr.next();
446 printSESELivenessTree( fsenChild );
451 private void variableAnalysisForward( FlatMethod fm ) {
453 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
454 flatNodesToVisit.add( fm );
456 while( !flatNodesToVisit.isEmpty() ) {
457 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
458 flatNodesToVisit.remove( fn );
460 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
461 assert seseStack != null;
463 VarSrcTokTable prev = variableResults.get( fn );
465 // merge sets from control flow joins
466 VarSrcTokTable curr = new VarSrcTokTable();
467 for( int i = 0; i < fn.numPrev(); i++ ) {
468 FlatNode nn = fn.getPrev( i );
469 VarSrcTokTable incoming = variableResults.get( nn );
470 curr.merge( incoming );
473 if( !seseStack.empty() ) {
474 variable_nodeActions( fn, curr, seseStack.peek() );
477 // if a new result, schedule forward nodes for analysis
478 if( !curr.equals( prev ) ) {
479 variableResults.put( fn, curr );
481 for( int i = 0; i < fn.numNext(); i++ ) {
482 FlatNode nn = fn.getNext( i );
483 flatNodesToVisit.add( nn );
489 private void variable_nodeActions( FlatNode fn,
490 VarSrcTokTable vstTable,
491 FlatSESEEnterNode currentSESE ) {
492 switch( fn.kind() ) {
494 case FKind.FlatSESEEnterNode: {
495 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
496 assert fsen.equals( currentSESE );
497 vstTable.age( currentSESE );
498 vstTable.assertConsistency();
501 case FKind.FlatSESEExitNode: {
502 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
503 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
504 assert currentSESE.getChildren().contains( fsen );
505 vstTable.remapChildTokens( fsen );
507 Set<TempDescriptor> liveIn = currentSESE.getInVarSet();
508 Set<TempDescriptor> virLiveIn = vstTable.removeParentAndSiblingTokens( fsen, liveIn );
509 Set<TempDescriptor> virLiveInOld = livenessVirtualReads.get( fn );
510 if( virLiveInOld != null ) {
511 virLiveIn.addAll( virLiveInOld );
513 livenessVirtualReads.put( fn, virLiveIn );
514 vstTable.assertConsistency();
516 // then all child out-set tokens are guaranteed
517 // to be filled in, so clobber those entries with
518 // the latest, clean sources
519 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
520 while( outVarItr.hasNext() ) {
521 TempDescriptor outVar = outVarItr.next();
522 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
524 VariableSourceToken vst = new VariableSourceToken( ts,
529 vstTable.remove( outVar );
532 vstTable.assertConsistency();
536 case FKind.FlatOpNode: {
537 FlatOpNode fon = (FlatOpNode) fn;
539 if( fon.getOp().getOp() == Operation.ASSIGN ) {
540 TempDescriptor lhs = fon.getDest();
541 TempDescriptor rhs = fon.getLeft();
543 vstTable.remove( lhs );
545 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
547 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
548 while( itr.hasNext() ) {
549 VariableSourceToken vst = itr.next();
551 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
554 forAddition.add( new VariableSourceToken( ts,
562 vstTable.addAll( forAddition );
564 // only break if this is an ASSIGN op node,
565 // otherwise fall through to default case
566 vstTable.assertConsistency();
571 // note that FlatOpNode's that aren't ASSIGN
572 // fall through to this default case
574 TempDescriptor [] writeTemps = fn.writesTemps();
575 if( writeTemps.length > 0 ) {
578 // for now, when writeTemps > 1, make sure
579 // its a call node, programmer enforce only
580 // doing stuff like calling a print routine
581 //assert writeTemps.length == 1;
582 if( writeTemps.length > 1 ) {
583 assert fn.kind() == FKind.FlatCall ||
584 fn.kind() == FKind.FlatMethod;
589 vstTable.remove( writeTemps[0] );
591 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
592 ts.add( writeTemps[0] );
594 vstTable.add( new VariableSourceToken( ts,
602 vstTable.assertConsistency();
609 private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
611 // start from flat method top, visit every node in
612 // method exactly once
613 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
614 flatNodesToVisit.add( fm );
616 Set<FlatNode> visited = new HashSet<FlatNode>();
618 while( !flatNodesToVisit.isEmpty() ) {
619 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
620 FlatNode fn = fnItr.next();
622 flatNodesToVisit.remove( fn );
625 Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
626 VarSrcTokTable vstTable = variableResults.get( fn );
628 // fix later, not working, only wanted it to make tables easier to read
629 //vstTable.pruneByLiveness( rootLiveSet );
631 for( int i = 0; i < fn.numNext(); i++ ) {
632 FlatNode nn = fn.getNext( i );
634 if( !visited.contains( nn ) ) {
635 flatNodesToVisit.add( nn );
642 private void notAvailableForward( FlatMethod fm ) {
644 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
645 flatNodesToVisit.add( fm );
647 while( !flatNodesToVisit.isEmpty() ) {
648 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
649 flatNodesToVisit.remove( fn );
651 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
652 assert seseStack != null;
654 Set<TempDescriptor> prev = notAvailableResults.get( fn );
656 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
657 for( int i = 0; i < fn.numPrev(); i++ ) {
658 FlatNode nn = fn.getPrev( i );
659 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
660 if( notAvailIn != null ) {
661 curr.addAll( notAvailIn );
665 if( !seseStack.empty() ) {
666 notAvailable_nodeActions( fn, curr, seseStack.peek() );
669 // if a new result, schedule forward nodes for analysis
670 if( !curr.equals( prev ) ) {
671 notAvailableResults.put( fn, curr );
673 for( int i = 0; i < fn.numNext(); i++ ) {
674 FlatNode nn = fn.getNext( i );
675 flatNodesToVisit.add( nn );
681 private void notAvailable_nodeActions( FlatNode fn,
682 Set<TempDescriptor> notAvailSet,
683 FlatSESEEnterNode currentSESE ) {
685 // any temps that are removed from the not available set
686 // at this node should be marked in this node's code plan
687 // as temps to be grabbed at runtime!
689 switch( fn.kind() ) {
691 case FKind.FlatSESEEnterNode: {
692 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
693 assert fsen.equals( currentSESE );
697 case FKind.FlatSESEExitNode: {
698 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
699 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
700 assert currentSESE.getChildren().contains( fsen );
702 Set<TempDescriptor> liveTemps = livenessRootView.get( fn );
703 assert liveTemps != null;
705 notAvailSet.addAll( liveTemps );
708 case FKind.FlatOpNode: {
709 FlatOpNode fon = (FlatOpNode) fn;
711 if( fon.getOp().getOp() == Operation.ASSIGN ) {
712 TempDescriptor lhs = fon.getDest();
713 TempDescriptor rhs = fon.getLeft();
715 // copy makes lhs same availability as rhs
716 if( notAvailSet.contains( rhs ) ) {
717 notAvailSet.add( lhs );
719 notAvailSet.remove( lhs );
722 // only break if this is an ASSIGN op node,
723 // otherwise fall through to default case
728 // note that FlatOpNode's that aren't ASSIGN
729 // fall through to this default case
731 TempDescriptor [] writeTemps = fn.writesTemps();
732 for( int i = 0; i < writeTemps.length; i++ ) {
733 TempDescriptor wTemp = writeTemps[i];
734 notAvailSet.remove( wTemp );
736 TempDescriptor [] readTemps = fn.readsTemps();
737 for( int i = 0; i < readTemps.length; i++ ) {
738 TempDescriptor rTemp = readTemps[i];
739 notAvailSet.remove( rTemp );
741 // if this variable has exactly one source, mark everything
742 // else from that source as available as well
743 VarSrcTokTable vstTable = variableResults.get( fn );
746 vstTable.getRefVarSrcType( rTemp,
748 currentSESE.getParent() );
750 if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
752 VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
754 Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
757 while( availItr.hasNext() ) {
758 VariableSourceToken vstAlsoAvail = availItr.next();
759 notAvailSet.removeAll( vstAlsoAvail.getRefVars() );
769 private void computeStallsForward( FlatMethod fm ) {
771 // start from flat method top, visit every node in
772 // method exactly once
773 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
774 flatNodesToVisit.add( fm );
776 Set<FlatNode> visited = new HashSet<FlatNode>();
778 while( !flatNodesToVisit.isEmpty() ) {
779 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
780 FlatNode fn = fnItr.next();
782 flatNodesToVisit.remove( fn );
785 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
786 assert seseStack != null;
788 // use incoming results as "dot statement" or just
789 // before the current statement
790 VarSrcTokTable dotSTtable = new VarSrcTokTable();
791 for( int i = 0; i < fn.numPrev(); i++ ) {
792 FlatNode nn = fn.getPrev( i );
793 dotSTtable.merge( variableResults.get( nn ) );
796 // find dt-st notAvailableSet also
797 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
798 for( int i = 0; i < fn.numPrev(); i++ ) {
799 FlatNode nn = fn.getPrev( i );
800 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
801 if( notAvailIn != null ) {
802 dotSTnotAvailSet.addAll( notAvailIn );
806 if( !seseStack.empty() ) {
807 computeStalls_nodeActions( fn, dotSTtable, dotSTnotAvailSet, seseStack.peek() );
810 for( int i = 0; i < fn.numNext(); i++ ) {
811 FlatNode nn = fn.getNext( i );
813 if( !visited.contains( nn ) ) {
814 flatNodesToVisit.add( nn );
820 private void computeStalls_nodeActions( FlatNode fn,
821 VarSrcTokTable vstTable,
822 Set<TempDescriptor> notAvailSet,
823 FlatSESEEnterNode currentSESE ) {
824 CodePlan plan = new CodePlan();
827 switch( fn.kind() ) {
829 case FKind.FlatSESEEnterNode: {
830 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
832 // track the source types of the in-var set so generated
833 // code at this SESE issue can compute the number of
834 // dependencies properly
835 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
836 while( inVarItr.hasNext() ) {
837 TempDescriptor inVar = inVarItr.next();
839 vstTable.getRefVarSrcType( inVar,
843 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
844 fsen.addDynamicInVar( inVar );
846 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
847 fsen.addStaticInVar( inVar );
848 VariableSourceToken vst = vstTable.get( inVar ).iterator().next();
849 fsen.putStaticInVar2src( inVar, vst );
850 fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(),
856 assert srcType.equals( VarSrcTokTable.SrcType_READY );
857 fsen.addReadyInVar( inVar );
863 case FKind.FlatSESEExitNode: {
864 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
867 case FKind.FlatOpNode: {
868 FlatOpNode fon = (FlatOpNode) fn;
870 if( fon.getOp().getOp() == Operation.ASSIGN ) {
871 // if this is an op node, don't stall, copy
872 // source and delay until we need to use value
874 // only break if this is an ASSIGN op node,
875 // otherwise fall through to default case
880 // note that FlatOpNode's that aren't ASSIGN
881 // fall through to this default case
884 // a node with no live set has nothing to stall for
885 Set<TempDescriptor> liveSet = livenessRootView.get( fn );
886 if( liveSet == null ) {
890 TempDescriptor[] readarray = fn.readsTemps();
891 for( int i = 0; i < readarray.length; i++ ) {
892 TempDescriptor readtmp = readarray[i];
894 // ignore temps that are definitely available
895 // when considering to stall on it
896 if( !notAvailSet.contains( readtmp ) ) {
900 // check the source type of this variable
902 = vstTable.getRefVarSrcType( readtmp,
904 currentSESE.getParent() );
907 System.out.println( "considering stall on "+readtmp+" for "+currentSESE );
909 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
910 // 1) It is not clear statically where this variable will
911 // come from statically, so dynamically we must keep track
912 // along various control paths, and therefore when we stall,
913 // just stall for the exact thing we need and move on
914 plan.addDynamicStall( readtmp );
915 currentSESE.addDynamicStallVar( readtmp );
916 System.out.println( "ADDING "+readtmp+" TO "+currentSESE+" DYNSTALLSET" );
918 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
919 // 2) Single token/age pair: Stall for token/age pair, and copy
920 // all live variables with same token/age pair at the same
921 // time. This is the same stuff that the notavaialable analysis
922 // marks as now available.
924 VariableSourceToken vst = vstTable.get( readtmp ).iterator().next();
926 Iterator<VariableSourceToken> availItr =
927 vstTable.get( vst.getSESE(), vst.getAge() ).iterator();
929 while( availItr.hasNext() ) {
930 VariableSourceToken vstAlsoAvail = availItr.next();
932 // only grab additional stuff that is live
933 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
935 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
936 while( refVarItr.hasNext() ) {
937 TempDescriptor refVar = refVarItr.next();
938 if( liveSet.contains( refVar ) ) {
939 copySet.add( refVar );
943 if( !copySet.isEmpty() ) {
944 plan.addStall2CopySet( vstAlsoAvail, copySet );
949 // the other case for srcs is READY from a parent, however
950 // since we are only examining variables that come from
951 // children tokens, this should never occur
955 // assert that everything being stalled for is in the
956 // "not available" set coming into this flat node and
957 // that every VST identified is in the possible "stall set"
958 // that represents VST's from children SESE's
966 // identify sese-age pairs that are statically useful
967 // and should have an associated SESE variable in code
968 Set<VariableSourceToken> staticSet = vstTable.getStaticSet();
969 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
970 while( vstItr.hasNext() ) {
971 VariableSourceToken vst = vstItr.next();
972 currentSESE.addNeededStaticName(
973 new SESEandAgePair( vst.getSESE(), vst.getAge() )
975 currentSESE.mustTrackAtLeastAge( vst.getAge() );
979 codePlans.put( fn, plan );
982 // if any variables at this node have a static source (exactly one vst)
983 // but go to a dynamic source at a next node, create a new IR graph
984 // node on that edge to track the sources dynamically
985 for( int i = 0; i < fn.numNext(); i++ ) {
986 FlatNode nn = fn.getNext( i );
987 VarSrcTokTable nextVstTable = variableResults.get( nn );
989 // the table can be null if it is one of the few IR nodes
990 // completely outside of the root SESE scope
991 if( nextVstTable != null ) {
993 Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet =
994 vstTable.getStatic2DynamicSet( nextVstTable );
996 if( !static2dynamicSet.isEmpty() ) {
998 // either add these results to partial fixed-point result
999 // or make a new one if we haven't made any here yet
1000 FlatEdge fe = new FlatEdge( fn, nn );
1001 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
1003 if( fwdvn == null ) {
1004 fwdvn = new FlatWriteDynamicVarNode( fn, nn, static2dynamicSet );
1005 wdvNodesToSpliceIn.put( fe, fwdvn );
1007 fwdvn.addMoreVar2Src( static2dynamicSet );