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 static int maxSESEage = -1;
33 // use these methods in BuildCode to have access to analysis results
34 public FlatSESEEnterNode getRootSESE() {
38 public Set<FlatSESEEnterNode> getAllSESEs() {
42 public int getMaxSESEage() {
47 public CodePlan getCodePlan( FlatNode fn ) {
48 CodePlan cp = codePlans.get( fn );
53 public MLPAnalysis( State state,
56 OwnershipAnalysis ownAnalysis
59 double timeStartAnalysis = (double) System.nanoTime();
63 this.callGraph = callGraph;
64 this.ownAnalysis = ownAnalysis;
65 this.maxSESEage = state.MLP_MAXSESEAGE;
67 // initialize analysis data structures
68 allSESEs = new HashSet<FlatSESEEnterNode>();
70 seseStacks = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
71 livenessVirtualReads = new Hashtable< FlatNode, Set<TempDescriptor> >();
72 variableResults = new Hashtable< FlatNode, VarSrcTokTable >();
73 notAvailableResults = new Hashtable< FlatNode, Set<TempDescriptor> >();
74 codePlans = new Hashtable< FlatNode, CodePlan >();
76 FlatMethod fmMain = state.getMethodFlat( tu.getMain() );
78 rootSESE = (FlatSESEEnterNode) fmMain.getNext(0);
82 // run analysis on each method that is actually called
83 // reachability analysis already computed this so reuse
84 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
85 while( methItr.hasNext() ) {
86 Descriptor d = methItr.next();
87 FlatMethod fm = state.getMethodFlat( d );
89 // find every SESE from methods that may be called
90 // and organize them into roots and children
91 buildForestForward( fm );
95 // 2nd pass, results are saved in FlatSESEEnterNode, so
96 // intermediate results, for safety, are discarded
97 livenessAnalysisBackward( rootSESE, true, null, fmMain.getFlatExit() );
101 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
102 while( methItr.hasNext() ) {
103 Descriptor d = methItr.next();
104 FlatMethod fm = state.getMethodFlat( d );
106 // starting from roots do a forward, fixed-point
107 // variable analysis for refinement and stalls
108 variableAnalysisForward( fm );
112 // 4th pass, compute liveness contribution from
113 // virtual reads discovered in variable pass
114 livenessAnalysisBackward( rootSESE, true, null, fmMain.getFlatExit() );
118 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
119 while( methItr.hasNext() ) {
120 Descriptor d = methItr.next();
121 FlatMethod fm = state.getMethodFlat( d );
123 // compute what is not available at every program
124 // point, in a forward fixed-point pass
125 notAvailableForward( fm );
130 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
131 while( methItr.hasNext() ) {
132 Descriptor d = methItr.next();
133 FlatMethod fm = state.getMethodFlat( d );
135 // compute a plan for code injections
136 computeStallsForward( fm );
140 if( state.MLPDEBUG ) {
141 System.out.println( "" );
142 //System.out.println( "\nSESE Hierarchy\n--------------\n" ); printSESEHierarchy();
143 //System.out.println( "\nSESE Liveness\n-------------\n" ); printSESELiveness();
144 System.out.println( "\nLiveness Root View\n------------------\n"+fmMain.printMethod( livenessRootView ) );
145 System.out.println( "\nVariable Results\n----------------\n"+fmMain.printMethod( variableResults ) );
146 System.out.println( "\nNot Available Results\n---------------------\n"+fmMain.printMethod( notAvailableResults ) );
147 System.out.println( "\nCode Plans\n----------\n"+fmMain.printMethod( codePlans ) );
151 double timeEndAnalysis = (double) System.nanoTime();
152 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
153 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
154 System.out.println( treport );
158 private void buildForestForward( FlatMethod fm ) {
160 // start from flat method top, visit every node in
161 // method exactly once, find SESEs and remember
162 // roots and child relationships
163 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
164 flatNodesToVisit.add( fm );
166 Set<FlatNode> visited = new HashSet<FlatNode>();
168 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
169 seseStacks.put( fm, seseStackFirst );
171 while( !flatNodesToVisit.isEmpty() ) {
172 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
173 FlatNode fn = fnItr.next();
175 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
176 assert seseStack != null;
178 flatNodesToVisit.remove( fn );
181 buildForest_nodeActions( fn, seseStack, fm );
183 for( int i = 0; i < fn.numNext(); i++ ) {
184 FlatNode nn = fn.getNext( i );
186 if( !visited.contains( nn ) ) {
187 flatNodesToVisit.add( nn );
189 // clone stack and send along each analysis path
190 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
196 private void buildForest_nodeActions( FlatNode fn,
197 Stack<FlatSESEEnterNode> seseStack,
199 switch( fn.kind() ) {
201 case FKind.FlatSESEEnterNode: {
202 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
204 allSESEs.add( fsen );
205 fsen.setEnclosingFlatMeth( fm );
207 if( !seseStack.empty() ) {
208 seseStack.peek().addChild( fsen );
209 fsen.setParent( seseStack.peek() );
212 seseStack.push( fsen );
215 case FKind.FlatSESEExitNode: {
216 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
217 assert !seseStack.empty();
218 FlatSESEEnterNode fsen = seseStack.pop();
221 case FKind.FlatReturnNode: {
222 FlatReturnNode frn = (FlatReturnNode) fn;
223 if( !seseStack.empty() ) {
224 throw new Error( "Error: return statement enclosed within SESE "+
225 seseStack.peek().getPrettyIdentifier() );
232 private void printSESEHierarchy() {
233 // our forest is actually a tree now that
234 // there is an implicit root SESE
235 printSESEHierarchyTree( rootSESE, 0 );
236 System.out.println( "" );
239 private void printSESEHierarchyTree( FlatSESEEnterNode fsen, int depth ) {
240 for( int i = 0; i < depth; ++i ) {
241 System.out.print( " " );
243 System.out.println( "- "+fsen.getPrettyIdentifier() );
245 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
246 while( childItr.hasNext() ) {
247 FlatSESEEnterNode fsenChild = childItr.next();
248 printSESEHierarchyTree( fsenChild, depth + 1 );
253 private void livenessAnalysisBackward( FlatSESEEnterNode fsen,
255 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout,
258 // start from an SESE exit, visit nodes in reverse up to
259 // SESE enter in a fixed-point scheme, where children SESEs
260 // should already be analyzed and therefore can be skipped
261 // because child SESE enter node has all necessary info
262 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
264 FlatSESEExitNode fsexn = fsen.getFlatExit();
267 flatNodesToVisit.add( fexit );
269 flatNodesToVisit.add( fsexn );
270 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults=new Hashtable<FlatNode, Set<TempDescriptor>>();
273 liveout=new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
275 while( !flatNodesToVisit.isEmpty() ) {
276 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
277 flatNodesToVisit.remove( fn );
279 Set<TempDescriptor> prev = livenessResults.get( fn );
281 // merge sets from control flow joins
282 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
283 for( int i = 0; i < fn.numNext(); i++ ) {
284 FlatNode nn = fn.getNext( i );
285 Set<TempDescriptor> s = livenessResults.get( nn );
291 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
293 // if a new result, schedule backward nodes for analysis
294 if( !curr.equals( prev ) ) {
295 livenessResults.put( fn, curr );
297 // don't flow backwards past current SESE enter
298 if( !fn.equals( fsen ) ) {
299 for( int i = 0; i < fn.numPrev(); i++ ) {
300 FlatNode nn = fn.getPrev( i );
301 flatNodesToVisit.add( nn );
307 Set<TempDescriptor> s = livenessResults.get( fsen );
309 fsen.addInVarSet( s );
312 // remember liveness per node from the root view as the
313 // global liveness of variables for later passes to use
314 if( toplevel == true ) {
315 livenessRootView = livenessResults;
318 // post-order traversal, so do children first
319 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
320 while( childItr.hasNext() ) {
321 FlatSESEEnterNode fsenChild = childItr.next();
322 livenessAnalysisBackward( fsenChild, false, liveout, null );
326 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
327 Set<TempDescriptor> liveIn,
328 FlatSESEEnterNode currentSESE,
330 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
332 switch( fn.kind() ) {
334 case FKind.FlatSESEExitNode:
335 if (toplevel==true) {
336 FlatSESEExitNode exitn=(FlatSESEExitNode) fn;
337 //update liveout set for FlatSESEExitNode
338 if (!liveout.containsKey(exitn))
339 liveout.put(exitn, new HashSet<TempDescriptor>());
340 liveout.get(exitn).addAll(liveIn);
342 // no break, sese exits should also execute default actions
345 // handle effects of statement in reverse, writes then reads
346 TempDescriptor [] writeTemps = fn.writesTemps();
347 for( int i = 0; i < writeTemps.length; ++i ) {
348 liveIn.remove( writeTemps[i] );
351 FlatSESEExitNode exitnode=currentSESE.getFlatExit();
352 Set<TempDescriptor> livetemps=liveout.get(exitnode);
353 if (livetemps.contains(writeTemps[i])) {
354 //write to a live out temp...
355 //need to put in SESE liveout set
356 currentSESE.addOutVar(writeTemps[i]);
361 TempDescriptor [] readTemps = fn.readsTemps();
362 for( int i = 0; i < readTemps.length; ++i ) {
363 liveIn.add( readTemps[i] );
366 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
367 if( virtualReadTemps != null ) {
368 Iterator<TempDescriptor> vrItr = virtualReadTemps.iterator();
369 while( vrItr.hasNext() ) {
370 TempDescriptor vrt = vrItr.next();
381 private void printSESELiveness() {
382 // our forest is actually a tree now that
383 // there is an implicit root SESE
384 printSESELivenessTree( rootSESE );
385 System.out.println( "" );
388 private void printSESELivenessTree( FlatSESEEnterNode fsen ) {
390 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
391 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
392 while( tItr.hasNext() ) {
393 System.out.println( " "+tItr.next() );
395 System.out.println( "and out-set:" );
396 tItr = fsen.getOutVarSet().iterator();
397 while( tItr.hasNext() ) {
398 System.out.println( " "+tItr.next() );
400 System.out.println( "" );
403 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
404 while( childItr.hasNext() ) {
405 FlatSESEEnterNode fsenChild = childItr.next();
406 printSESELivenessTree( fsenChild );
411 private void variableAnalysisForward( FlatMethod fm ) {
413 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
414 flatNodesToVisit.add( fm );
416 while( !flatNodesToVisit.isEmpty() ) {
417 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
418 flatNodesToVisit.remove( fn );
420 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
421 assert seseStack != null;
423 VarSrcTokTable prev = variableResults.get( fn );
425 // merge sets from control flow joins
426 VarSrcTokTable curr = new VarSrcTokTable();
427 for( int i = 0; i < fn.numPrev(); i++ ) {
428 FlatNode nn = fn.getPrev( i );
429 VarSrcTokTable incoming = variableResults.get( nn );
430 curr.merge( incoming );
433 if( !seseStack.empty() ) {
434 variable_nodeActions( fn, curr, seseStack.peek() );
437 // if a new result, schedule forward nodes for analysis
438 if( !curr.equals( prev ) ) {
439 variableResults.put( fn, curr );
441 for( int i = 0; i < fn.numNext(); i++ ) {
442 FlatNode nn = fn.getNext( i );
443 flatNodesToVisit.add( nn );
449 private void variable_nodeActions( FlatNode fn,
450 VarSrcTokTable vstTable,
451 FlatSESEEnterNode currentSESE ) {
452 switch( fn.kind() ) {
454 case FKind.FlatSESEEnterNode: {
455 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
456 assert fsen.equals( currentSESE );
457 vstTable.age( currentSESE );
458 vstTable.assertConsistency();
461 case FKind.FlatSESEExitNode: {
462 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
463 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
464 assert currentSESE.getChildren().contains( fsen );
465 vstTable.remapChildTokens( fsen );
467 Set<TempDescriptor> liveIn = currentSESE.getInVarSet();
468 Set<TempDescriptor> virLiveIn = vstTable.removeParentAndSiblingTokens( fsen, liveIn );
469 Set<TempDescriptor> virLiveInOld = livenessVirtualReads.get( fn );
470 if( virLiveInOld != null ) {
471 virLiveIn.addAll( virLiveInOld );
473 livenessVirtualReads.put( fn, virLiveIn );
474 vstTable.assertConsistency();
477 case FKind.FlatOpNode: {
478 FlatOpNode fon = (FlatOpNode) fn;
480 if( fon.getOp().getOp() == Operation.ASSIGN ) {
481 TempDescriptor lhs = fon.getDest();
482 TempDescriptor rhs = fon.getLeft();
484 vstTable.remove( lhs );
486 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
488 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
489 while( itr.hasNext() ) {
490 VariableSourceToken vst = itr.next();
492 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
495 // if this is from a child, keep the source information
496 if( currentSESE.getChildren().contains( vst.getSESE() ) ) {
497 forAddition.add( new VariableSourceToken( ts,
504 // otherwise, it's our or an ancestor's token so we
505 // can assume we have everything we need
507 forAddition.add( new VariableSourceToken( ts,
516 vstTable.addAll( forAddition );
518 // only break if this is an ASSIGN op node,
519 // otherwise fall through to default case
520 vstTable.assertConsistency();
525 // note that FlatOpNode's that aren't ASSIGN
526 // fall through to this default case
528 TempDescriptor [] writeTemps = fn.writesTemps();
529 if( writeTemps.length > 0 ) {
532 // for now, when writeTemps > 1, make sure
533 // its a call node, programmer enforce only
534 // doing stuff like calling a print routine
535 //assert writeTemps.length == 1;
536 if( writeTemps.length > 1 ) {
537 assert fn.kind() == FKind.FlatCall ||
538 fn.kind() == FKind.FlatMethod;
543 vstTable.remove( writeTemps[0] );
545 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
546 ts.add( writeTemps[0] );
548 vstTable.add( new VariableSourceToken( ts,
556 vstTable.assertConsistency();
563 private void notAvailableForward( FlatMethod fm ) {
565 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
566 flatNodesToVisit.add( fm );
568 while( !flatNodesToVisit.isEmpty() ) {
569 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
570 flatNodesToVisit.remove( fn );
572 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
573 assert seseStack != null;
575 Set<TempDescriptor> prev = notAvailableResults.get( fn );
577 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
578 for( int i = 0; i < fn.numPrev(); i++ ) {
579 FlatNode nn = fn.getPrev( i );
580 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
581 if( notAvailIn != null ) {
582 curr.addAll( notAvailIn );
586 if( !seseStack.empty() ) {
587 notAvailable_nodeActions( fn, curr, seseStack.peek() );
590 // if a new result, schedule forward nodes for analysis
591 if( !curr.equals( prev ) ) {
592 notAvailableResults.put( fn, curr );
594 for( int i = 0; i < fn.numNext(); i++ ) {
595 FlatNode nn = fn.getNext( i );
596 flatNodesToVisit.add( nn );
602 private void notAvailable_nodeActions( FlatNode fn,
603 Set<TempDescriptor> notAvailSet,
604 FlatSESEEnterNode currentSESE ) {
606 // any temps that are removed from the not available set
607 // at this node should be marked in this node's code plan
608 // as temps to be grabbed at runtime!
610 switch( fn.kind() ) {
612 case FKind.FlatSESEEnterNode: {
613 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
614 assert fsen.equals( currentSESE );
618 case FKind.FlatSESEExitNode: {
619 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
620 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
621 assert currentSESE.getChildren().contains( fsen );
623 Set<TempDescriptor> liveTemps = livenessRootView.get( fn );
624 assert liveTemps != null;
626 VarSrcTokTable vstTable = variableResults.get( fn );
627 assert vstTable != null;
629 Set<TempDescriptor> notAvailAtEnter = notAvailableResults.get( fsen );
630 assert notAvailAtEnter != null;
632 Iterator<TempDescriptor> tdItr = liveTemps.iterator();
633 while( tdItr.hasNext() ) {
634 TempDescriptor td = tdItr.next();
636 if( vstTable.get( fsen, td ).size() > 0 ) {
637 // there is at least one child token for this variable
638 notAvailSet.add( td );
642 if( notAvailAtEnter.contains( td ) ) {
643 // wasn't available at enter, not available now
644 notAvailSet.add( td );
650 case FKind.FlatOpNode: {
651 FlatOpNode fon = (FlatOpNode) fn;
653 if( fon.getOp().getOp() == Operation.ASSIGN ) {
654 TempDescriptor lhs = fon.getDest();
655 TempDescriptor rhs = fon.getLeft();
657 // copy makes lhs same availability as rhs
658 if( notAvailSet.contains( rhs ) ) {
659 notAvailSet.add( lhs );
661 notAvailSet.remove( lhs );
664 // only break if this is an ASSIGN op node,
665 // otherwise fall through to default case
670 // note that FlatOpNode's that aren't ASSIGN
671 // fall through to this default case
673 TempDescriptor [] writeTemps = fn.writesTemps();
674 for( int i = 0; i < writeTemps.length; i++ ) {
675 TempDescriptor wTemp = writeTemps[i];
676 notAvailSet.remove( wTemp );
678 TempDescriptor [] readTemps = fn.readsTemps();
679 for( int i = 0; i < readTemps.length; i++ ) {
680 TempDescriptor rTemp = readTemps[i];
681 notAvailSet.remove( rTemp );
683 // if this variable has exactly one source, mark everything
684 // else from that source as available as well
685 VarSrcTokTable table = variableResults.get( fn );
686 Set<VariableSourceToken> srcs = table.get( rTemp );
688 if( srcs.size() == 1 ) {
689 VariableSourceToken vst = srcs.iterator().next();
691 Iterator<VariableSourceToken> availItr = table.get( vst.getSESE(),
694 while( availItr.hasNext() ) {
695 VariableSourceToken vstAlsoAvail = availItr.next();
696 notAvailSet.removeAll( vstAlsoAvail.getRefVars() );
706 private void computeStallsForward( FlatMethod fm ) {
708 // start from flat method top, visit every node in
709 // method exactly once
710 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
711 flatNodesToVisit.add( fm );
713 Set<FlatNode> visited = new HashSet<FlatNode>();
715 while( !flatNodesToVisit.isEmpty() ) {
716 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
717 FlatNode fn = fnItr.next();
719 flatNodesToVisit.remove( fn );
722 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
723 assert seseStack != null;
725 // use incoming results as "dot statement" or just
726 // before the current statement
727 VarSrcTokTable dotSTtable = new VarSrcTokTable();
728 for( int i = 0; i < fn.numPrev(); i++ ) {
729 FlatNode nn = fn.getPrev( i );
730 dotSTtable.merge( variableResults.get( nn ) );
733 // find dt-st notAvailableSet also
734 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
735 for( int i = 0; i < fn.numPrev(); i++ ) {
736 FlatNode nn = fn.getPrev( i );
737 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
738 if( notAvailIn != null ) {
739 dotSTnotAvailSet.addAll( notAvailIn );
743 if( !seseStack.empty() ) {
744 computeStalls_nodeActions( fn, dotSTtable, dotSTnotAvailSet, seseStack.peek() );
747 for( int i = 0; i < fn.numNext(); i++ ) {
748 FlatNode nn = fn.getNext( i );
750 if( !visited.contains( nn ) ) {
751 flatNodesToVisit.add( nn );
757 private void computeStalls_nodeActions( FlatNode fn,
758 VarSrcTokTable vstTable,
759 Set<TempDescriptor> notAvailSet,
760 FlatSESEEnterNode currentSESE ) {
761 CodePlan plan = new CodePlan();
764 switch( fn.kind() ) {
766 case FKind.FlatSESEEnterNode: {
767 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
770 case FKind.FlatSESEExitNode: {
771 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
774 case FKind.FlatOpNode: {
775 FlatOpNode fon = (FlatOpNode) fn;
777 if( fon.getOp().getOp() == Operation.ASSIGN ) {
778 // if this is an op node, don't stall, copy
779 // source and delay until we need to use value
781 // only break if this is an ASSIGN op node,
782 // otherwise fall through to default case
787 // note that FlatOpNode's that aren't ASSIGN
788 // fall through to this default case
790 // decide if we must stall for variables dereferenced at this node
791 Set<VariableSourceToken> stallSet = vstTable.getStallSet( currentSESE );
793 // a node with no live set has nothing to stall for
794 Set<TempDescriptor> liveSet = livenessRootView.get( fn );
795 if( liveSet == null ) {
799 TempDescriptor[] readarray = fn.readsTemps();
800 for( int i = 0; i < readarray.length; i++ ) {
801 TempDescriptor readtmp = readarray[i];
803 // ignore temps that are definitely available
804 // when considering to stall on it
805 if( !notAvailSet.contains( readtmp ) ) {
810 Set<VariableSourceToken> srcs = vstTable.get( readtmp );
811 assert !srcs.isEmpty();
813 // 1) Multiple token/age pairs or unknown age: Stall for
814 // dynamic name only.
815 if( srcs.size() > 1 ||
816 srcs.iterator().next().getAge() == maxSESEage ) {
820 // 2) Single token/age pair: Stall for token/age pair, and copy
821 // all live variables with same token/age pair at the same
822 // time. This is the same stuff that the notavaialable analysis
823 // marks as now available.
825 VariableSourceToken vst = srcs.iterator().next();
827 Iterator<VariableSourceToken> availItr =
828 vstTable.get( vst.getSESE(),
832 System.out.println( "Considering a stall on "+vst+
833 " and also getting\n "+vstTable.get( vst.getSESE(),
837 // only grab additional stuff that is live
838 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
840 while( availItr.hasNext() ) {
841 VariableSourceToken vstAlsoAvail = availItr.next();
843 if( liveSet.contains( vstAlsoAvail.getAddrVar() ) ) {
844 copySet.add( vstAlsoAvail.getAddrVar() );
848 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
849 while( refVarItr.hasNext() ) {
850 TempDescriptor refVar = refVarItr.next();
851 if( liveSet.contains( refVar ) ) {
852 copySet.add( refVar );
859 SESEandAgePair stallPair = new SESEandAgePair( vst.getSESE(), vst.getAge() );
860 plan.addStall2CopySet( stallPair, copySet );
861 System.out.println( "("+stallPair+"->"+copySet+")" );
864 // assert that everything being stalled for is in the
865 // "not available" set coming into this flat node and
866 // that every VST identified is in the possible "stall set"
867 // that represents VST's from children SESE's
875 // identify sese-age pairs that are statically useful
876 // and should have an associated SESE variable in code
877 Set<VariableSourceToken> staticSet = vstTable.getStaticSet();
878 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
879 while( vstItr.hasNext() ) {
880 VariableSourceToken vst = vstItr.next();
881 currentSESE.addNeededStaticName(
882 new SESEandAgePair( vst.getSESE(), vst.getAge() )
886 // if any variable at this node has a static source (exactly one sese)
887 // but goes to a dynamic source at a next node, write its dynamic addr
888 Set<VariableSourceToken> static2dynamicSet = new HashSet<VariableSourceToken>();
889 for( int i = 0; i < fn.numNext(); i++ ) {
890 FlatNode nn = fn.getNext( i );
891 VarSrcTokTable nextVstTable = variableResults.get( nn );
892 // the table can be null if it is one of the few IR nodes
893 // completely outside of the root SESE scope
894 if( nextVstTable != null ) {
895 static2dynamicSet.addAll( vstTable.getStatic2DynamicSet( nextVstTable ) );
899 if( !static2dynamicSet.isEmpty() ) {
900 plan.setWriteToDynamicSrc( static2dynamicSet );
903 codePlans.put( fn, plan );