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;
22 // an implicit SESE is automatically spliced into
23 // the IR graph around the C main before this analysis--it
24 // is nothing special except that we can make assumptions
25 // about it, such as the whole program ends when it ends
26 private FlatSESEEnterNode mainSESE;
28 // SESEs that are the root of an SESE tree belong to this
29 // set--the main SESE is always a root, statically SESEs
30 // inside methods are a root because we don't know how they
31 // will fit into the runtime tree of SESEs
32 private Set<FlatSESEEnterNode> rootSESEs;
34 // simply a set of every reachable SESE in the program
35 private Set<FlatSESEEnterNode> allSESEs;
38 // A mapping of flat nodes to the stack of SESEs for that node, where
39 // an SESE is the child of the SESE directly below it on the stack.
40 // These stacks do not reflect the heirarchy over methods calls--whenever
41 // there is an empty stack it means all variables are available.
42 private Hashtable< FlatNode, Stack<FlatSESEEnterNode> > seseStacks;
44 private Hashtable< FlatNode, Set<TempDescriptor> > livenessRootView;
45 private Hashtable< FlatNode, Set<TempDescriptor> > livenessVirtualReads;
46 private Hashtable< FlatNode, VarSrcTokTable > variableResults;
47 private Hashtable< FlatNode, Set<TempDescriptor> > notAvailableResults;
48 private Hashtable< FlatNode, CodePlan > codePlans;
50 private Hashtable< FlatEdge, FlatWriteDynamicVarNode > wdvNodesToSpliceIn;
52 public static int maxSESEage = -1;
55 // use these methods in BuildCode to have access to analysis results
56 public FlatSESEEnterNode getMainSESE() {
60 public Set<FlatSESEEnterNode> getRootSESEs() {
64 public Set<FlatSESEEnterNode> getAllSESEs() {
68 public int getMaxSESEage() {
73 public CodePlan getCodePlan( FlatNode fn ) {
74 CodePlan cp = codePlans.get( fn );
79 public MLPAnalysis( State state,
82 OwnershipAnalysis ownAnalysis
85 double timeStartAnalysis = (double) System.nanoTime();
89 this.callGraph = callGraph;
90 this.ownAnalysis = ownAnalysis;
91 this.maxSESEage = state.MLP_MAXSESEAGE;
93 rootSESEs = new HashSet<FlatSESEEnterNode>();
94 allSESEs = new HashSet<FlatSESEEnterNode>();
96 seseStacks = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
97 livenessRootView = new Hashtable< FlatNode, Set<TempDescriptor> >();
98 livenessVirtualReads = new Hashtable< FlatNode, Set<TempDescriptor> >();
99 variableResults = new Hashtable< FlatNode, VarSrcTokTable >();
100 notAvailableResults = new Hashtable< FlatNode, Set<TempDescriptor> >();
101 codePlans = new Hashtable< FlatNode, CodePlan >();
102 wdvNodesToSpliceIn = new Hashtable< FlatEdge, FlatWriteDynamicVarNode >();
105 FlatMethod fmMain = state.getMethodFlat( tu.getMain() );
107 mainSESE = (FlatSESEEnterNode) fmMain.getNext(0);
108 mainSESE.setfmEnclosing( fmMain );
109 mainSESE.setmdEnclosing( fmMain.getMethod() );
110 mainSESE.setcdEnclosing( fmMain.getMethod().getClassDesc() );
113 if( state.MLPDEBUG ) {
114 System.out.println( "" );
118 // run analysis on each method that is actually called
119 // reachability analysis already computed this so reuse
120 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
121 while( methItr.hasNext() ) {
122 Descriptor d = methItr.next();
123 FlatMethod fm = state.getMethodFlat( d );
125 // find every SESE from methods that may be called
126 // and organize them into roots and children
127 buildForestForward( fm );
129 if( state.MLPDEBUG ) {
130 System.out.println( "\nSESE Hierarchy\n--------------\n" ); printSESEHierarchy();
134 // 2nd pass, results are saved in FlatSESEEnterNode, so
135 // intermediate results, for safety, are discarded
136 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
137 while( rootItr.hasNext() ) {
138 FlatSESEEnterNode root = rootItr.next();
139 livenessAnalysisBackward( root,
142 root.getfmEnclosing().getFlatExit() );
147 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
148 while( methItr.hasNext() ) {
149 Descriptor d = methItr.next();
150 FlatMethod fm = state.getMethodFlat( d );
152 // starting from roots do a forward, fixed-point
153 // variable analysis for refinement and stalls
154 variableAnalysisForward( fm );
158 // 4th pass, compute liveness contribution from
159 // virtual reads discovered in variable pass
160 rootItr = rootSESEs.iterator();
161 while( rootItr.hasNext() ) {
162 FlatSESEEnterNode root = rootItr.next();
163 livenessAnalysisBackward( root,
166 root.getfmEnclosing().getFlatExit() );
168 if( state.MLPDEBUG ) {
169 //System.out.println( "\nLive-In, SESE View\n-------------\n" ); printSESELiveness();
170 //System.out.println( "\nLive-In, Root View\n------------------\n"+fmMain.printMethod( livenessRootView ) );
175 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
176 while( methItr.hasNext() ) {
177 Descriptor d = methItr.next();
178 FlatMethod fm = state.getMethodFlat( d );
180 // prune variable results in one traversal
181 // by removing reference variables that are not live
182 pruneVariableResultsWithLiveness( fm );
184 if( state.MLPDEBUG ) {
185 System.out.println( "\nVariable Results-Out\n----------------\n"+fmMain.printMethod( variableResults ) );
190 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
191 while( methItr.hasNext() ) {
192 Descriptor d = methItr.next();
193 FlatMethod fm = state.getMethodFlat( d );
195 // compute what is not available at every program
196 // point, in a forward fixed-point pass
197 notAvailableForward( fm );
199 if( state.MLPDEBUG ) {
200 //System.out.println( "\nNot Available Results-Out\n---------------------\n"+fmMain.printMethod( notAvailableResults ) );
205 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
206 while( methItr.hasNext() ) {
207 Descriptor d = methItr.next();
208 FlatMethod fm = state.getMethodFlat( d );
210 // compute a plan for code injections
211 codePlansForward( fm );
213 if( state.MLPDEBUG ) {
214 System.out.println( "\nCode Plans\n----------\n"+fmMain.printMethod( codePlans ) );
217 // splice new IR nodes into graph after all
218 // analysis passes are complete
219 Iterator spliceItr = wdvNodesToSpliceIn.entrySet().iterator();
220 while( spliceItr.hasNext() ) {
221 Map.Entry me = (Map.Entry) spliceItr.next();
222 FlatWriteDynamicVarNode fwdvn = (FlatWriteDynamicVarNode) me.getValue();
223 fwdvn.spliceIntoIR();
226 // detailed per-SESE information
227 if( state.MLPDEBUG ) {
228 System.out.println( "\nSESE info\n-------------\n" ); printSESEInfo();
231 double timeEndAnalysis = (double) System.nanoTime();
232 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
233 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
234 System.out.println( treport );
238 private void buildForestForward( FlatMethod fm ) {
240 // start from flat method top, visit every node in
241 // method exactly once, find SESEs and remember
242 // roots and child relationships
243 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
244 flatNodesToVisit.add( fm );
246 Set<FlatNode> visited = new HashSet<FlatNode>();
248 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
249 seseStacks.put( fm, seseStackFirst );
251 while( !flatNodesToVisit.isEmpty() ) {
252 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
253 FlatNode fn = fnItr.next();
255 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
256 assert seseStack != null;
258 flatNodesToVisit.remove( fn );
261 buildForest_nodeActions( fn, seseStack, fm );
263 for( int i = 0; i < fn.numNext(); i++ ) {
264 FlatNode nn = fn.getNext( i );
266 if( !visited.contains( nn ) ) {
267 flatNodesToVisit.add( nn );
269 // clone stack and send along each analysis path
270 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
276 private void buildForest_nodeActions( FlatNode fn,
277 Stack<FlatSESEEnterNode> seseStack,
279 switch( fn.kind() ) {
281 case FKind.FlatSESEEnterNode: {
282 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
284 allSESEs.add( fsen );
285 fsen.setfmEnclosing( fm );
286 fsen.setmdEnclosing( fm.getMethod() );
287 fsen.setcdEnclosing( fm.getMethod().getClassDesc() );
289 if( seseStack.empty() ) {
290 rootSESEs.add( fsen );
291 fsen.setParent( null );
293 seseStack.peek().addChild( fsen );
294 fsen.setParent( seseStack.peek() );
297 seseStack.push( fsen );
300 case FKind.FlatSESEExitNode: {
301 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
302 assert !seseStack.empty();
303 FlatSESEEnterNode fsen = seseStack.pop();
306 case FKind.FlatReturnNode: {
307 FlatReturnNode frn = (FlatReturnNode) fn;
308 if( !seseStack.empty() ) {
309 throw new Error( "Error: return statement enclosed within SESE "+
310 seseStack.peek().getPrettyIdentifier() );
317 private void printSESEHierarchy() {
318 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
319 while( rootItr.hasNext() ) {
320 FlatSESEEnterNode root = rootItr.next();
321 printSESEHierarchyTree( root, 0 );
323 System.out.println( "" );
326 private void printSESEHierarchyTree( FlatSESEEnterNode fsen, int depth ) {
327 for( int i = 0; i < depth; ++i ) {
328 System.out.print( " " );
330 System.out.println( "- "+fsen.getPrettyIdentifier() );
332 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
333 while( childItr.hasNext() ) {
334 FlatSESEEnterNode fsenChild = childItr.next();
335 printSESEHierarchyTree( fsenChild, depth + 1 );
340 private void livenessAnalysisBackward( FlatSESEEnterNode fsen,
342 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout,
345 // start from an SESE exit, visit nodes in reverse up to
346 // SESE enter in a fixed-point scheme, where children SESEs
347 // should already be analyzed and therefore can be skipped
348 // because child SESE enter node has all necessary info
349 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
351 FlatSESEExitNode fsexn = fsen.getFlatExit();
354 flatNodesToVisit.add( fexit );
356 flatNodesToVisit.add( fsexn );
357 Hashtable<FlatNode, Set<TempDescriptor>> livenessResults=new Hashtable<FlatNode, Set<TempDescriptor>>();
360 liveout=new Hashtable<FlatSESEExitNode, Set<TempDescriptor>>();
362 while( !flatNodesToVisit.isEmpty() ) {
363 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
364 flatNodesToVisit.remove( fn );
366 Set<TempDescriptor> prev = livenessResults.get( fn );
368 // merge sets from control flow joins
369 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
370 for( int i = 0; i < fn.numNext(); i++ ) {
371 FlatNode nn = fn.getNext( i );
372 Set<TempDescriptor> s = livenessResults.get( nn );
378 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen, toplevel, liveout);
380 // if a new result, schedule backward nodes for analysis
381 if( !curr.equals( prev ) ) {
382 livenessResults.put( fn, curr );
384 // don't flow backwards past current SESE enter
385 if( !fn.equals( fsen ) ) {
386 for( int i = 0; i < fn.numPrev(); i++ ) {
387 FlatNode nn = fn.getPrev( i );
388 flatNodesToVisit.add( nn );
394 Set<TempDescriptor> s = livenessResults.get( fsen );
396 fsen.addInVarSet( s );
399 // remember liveness per node from the root view as the
400 // global liveness of variables for later passes to use
401 if( toplevel == true ) {
402 livenessRootView.putAll( livenessResults );
405 // post-order traversal, so do children first
406 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
407 while( childItr.hasNext() ) {
408 FlatSESEEnterNode fsenChild = childItr.next();
409 livenessAnalysisBackward( fsenChild, false, liveout, null );
413 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
414 Set<TempDescriptor> liveIn,
415 FlatSESEEnterNode currentSESE,
417 Hashtable< FlatSESEExitNode, Set<TempDescriptor> > liveout ) {
419 switch( fn.kind() ) {
421 case FKind.FlatSESEExitNode:
422 if (toplevel==true) {
423 FlatSESEExitNode exitn=(FlatSESEExitNode) fn;
424 //update liveout set for FlatSESEExitNode
425 if (!liveout.containsKey(exitn))
426 liveout.put(exitn, new HashSet<TempDescriptor>());
427 liveout.get(exitn).addAll(liveIn);
429 // no break, sese exits should also execute default actions
432 // handle effects of statement in reverse, writes then reads
433 TempDescriptor [] writeTemps = fn.writesTemps();
434 for( int i = 0; i < writeTemps.length; ++i ) {
435 liveIn.remove( writeTemps[i] );
438 FlatSESEExitNode exitnode=currentSESE.getFlatExit();
439 Set<TempDescriptor> livetemps=liveout.get(exitnode);
440 if (livetemps.contains(writeTemps[i])) {
441 //write to a live out temp...
442 //need to put in SESE liveout set
443 currentSESE.addOutVar(writeTemps[i]);
448 TempDescriptor [] readTemps = fn.readsTemps();
449 for( int i = 0; i < readTemps.length; ++i ) {
450 liveIn.add( readTemps[i] );
453 Set<TempDescriptor> virtualReadTemps = livenessVirtualReads.get( fn );
454 if( virtualReadTemps != null ) {
455 Iterator<TempDescriptor> vrItr = virtualReadTemps.iterator();
456 while( vrItr.hasNext() ) {
457 TempDescriptor vrt = vrItr.next();
468 private void printSESELiveness() {
469 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
470 while( rootItr.hasNext() ) {
471 FlatSESEEnterNode root = rootItr.next();
472 printSESELivenessTree( root );
474 System.out.println( "" );
477 private void printSESELivenessTree( FlatSESEEnterNode fsen ) {
479 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
480 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
481 while( tItr.hasNext() ) {
482 System.out.println( " "+tItr.next() );
484 System.out.println( "and out-set:" );
485 tItr = fsen.getOutVarSet().iterator();
486 while( tItr.hasNext() ) {
487 System.out.println( " "+tItr.next() );
489 System.out.println( "" );
492 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
493 while( childItr.hasNext() ) {
494 FlatSESEEnterNode fsenChild = childItr.next();
495 printSESELivenessTree( fsenChild );
499 private void printSESEInfo() {
500 Iterator<FlatSESEEnterNode> rootItr = rootSESEs.iterator();
501 while( rootItr.hasNext() ) {
502 FlatSESEEnterNode root = rootItr.next();
503 printSESEInfoTree( root );
505 System.out.println( "" );
508 private void printSESEInfoTree( FlatSESEEnterNode fsen ) {
510 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" {" );
512 System.out.println( " in-set: "+fsen.getInVarSet() );
513 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
514 while( tItr.hasNext() ) {
515 TempDescriptor inVar = tItr.next();
516 if( fsen.getReadyInVarSet().contains( inVar ) ) {
517 System.out.println( " (ready) "+inVar );
519 if( fsen.getStaticInVarSet().contains( inVar ) ) {
520 System.out.println( " (static) "+inVar );
522 if( fsen.getDynamicInVarSet().contains( inVar ) ) {
523 System.out.println( " (dynamic)"+inVar );
527 System.out.println( " out-set: "+fsen.getOutVarSet() );
530 System.out.println( " static names to track:" );
531 tItr = fsen.getOutVarSet().iterator();
532 while( tItr.hasNext() ) {
533 System.out.println( " "+tItr.next() );
537 System.out.println( "}" );
539 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
540 while( childItr.hasNext() ) {
541 FlatSESEEnterNode fsenChild = childItr.next();
542 printSESEInfoTree( fsenChild );
547 private void variableAnalysisForward( FlatMethod fm ) {
549 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
550 flatNodesToVisit.add( fm );
552 while( !flatNodesToVisit.isEmpty() ) {
553 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
554 flatNodesToVisit.remove( fn );
556 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
557 assert seseStack != null;
559 VarSrcTokTable prev = variableResults.get( fn );
561 // merge sets from control flow joins
562 VarSrcTokTable curr = new VarSrcTokTable();
563 for( int i = 0; i < fn.numPrev(); i++ ) {
564 FlatNode nn = fn.getPrev( i );
565 VarSrcTokTable incoming = variableResults.get( nn );
566 curr.merge( incoming );
569 if( !seseStack.empty() ) {
570 variable_nodeActions( fn, curr, seseStack.peek() );
573 // if a new result, schedule forward nodes for analysis
574 if( !curr.equals( prev ) ) {
575 variableResults.put( fn, curr );
577 for( int i = 0; i < fn.numNext(); i++ ) {
578 FlatNode nn = fn.getNext( i );
579 flatNodesToVisit.add( nn );
585 private void variable_nodeActions( FlatNode fn,
586 VarSrcTokTable vstTable,
587 FlatSESEEnterNode currentSESE ) {
588 switch( fn.kind() ) {
590 case FKind.FlatSESEEnterNode: {
591 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
592 assert fsen.equals( currentSESE );
594 vstTable.age( currentSESE );
595 vstTable.assertConsistency();
597 //vstTable.ownInSet( currentSESE );
598 //vstTable.assertConsistency();
601 case FKind.FlatSESEExitNode: {
602 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
603 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
604 assert currentSESE.getChildren().contains( fsen );
606 vstTable.remapChildTokens( fsen );
608 // liveness virtual reads are things written by an SESE
609 // that, if not already, should be added to the in-set
610 Set<TempDescriptor> liveIn = currentSESE.getInVarSet();
611 Set<TempDescriptor> virLiveIn = vstTable.removeParentAndSiblingTokens( fsen, liveIn );
612 virLiveIn.addAll( fsen.getOutVarSet() );
613 Set<TempDescriptor> virLiveInOld = livenessVirtualReads.get( fn );
614 if( virLiveInOld != null ) {
615 virLiveIn.addAll( virLiveInOld );
617 livenessVirtualReads.put( fn, virLiveIn );
619 vstTable.assertConsistency();
622 // then all child out-set tokens are guaranteed
623 // to be filled in, so clobber those entries with
624 // the latest, clean sources
625 Iterator<TempDescriptor> outVarItr = fsen.getOutVarSet().iterator();
626 while( outVarItr.hasNext() ) {
627 TempDescriptor outVar = outVarItr.next();
628 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
630 VariableSourceToken vst =
631 new VariableSourceToken( ts,
636 vstTable.remove( outVar );
639 vstTable.assertConsistency();
643 case FKind.FlatOpNode: {
644 FlatOpNode fon = (FlatOpNode) fn;
646 if( fon.getOp().getOp() == Operation.ASSIGN ) {
647 TempDescriptor lhs = fon.getDest();
648 TempDescriptor rhs = fon.getLeft();
650 vstTable.remove( lhs );
652 Set<VariableSourceToken> forAddition = new HashSet<VariableSourceToken>();
654 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
655 while( itr.hasNext() ) {
656 VariableSourceToken vst = itr.next();
658 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
661 forAddition.add( new VariableSourceToken( ts,
669 vstTable.addAll( forAddition );
671 // only break if this is an ASSIGN op node,
672 // otherwise fall through to default case
673 vstTable.assertConsistency();
678 // note that FlatOpNode's that aren't ASSIGN
679 // fall through to this default case
681 TempDescriptor [] writeTemps = fn.writesTemps();
682 if( writeTemps.length > 0 ) {
685 // for now, when writeTemps > 1, make sure
686 // its a call node, programmer enforce only
687 // doing stuff like calling a print routine
688 //assert writeTemps.length == 1;
689 if( writeTemps.length > 1 ) {
690 assert fn.kind() == FKind.FlatCall ||
691 fn.kind() == FKind.FlatMethod;
696 vstTable.remove( writeTemps[0] );
698 HashSet<TempDescriptor> ts = new HashSet<TempDescriptor>();
699 ts.add( writeTemps[0] );
701 vstTable.add( new VariableSourceToken( ts,
709 vstTable.assertConsistency();
716 private void pruneVariableResultsWithLiveness( FlatMethod fm ) {
718 // start from flat method top, visit every node in
719 // method exactly once
720 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
721 flatNodesToVisit.add( fm );
723 Set<FlatNode> visited = new HashSet<FlatNode>();
725 while( !flatNodesToVisit.isEmpty() ) {
726 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
727 FlatNode fn = fnItr.next();
729 flatNodesToVisit.remove( fn );
732 Set<TempDescriptor> rootLiveSet = livenessRootView.get( fn );
733 VarSrcTokTable vstTable = variableResults.get( fn );
735 // fix later, not working, only wanted it to make tables easier to read
736 vstTable.pruneByLiveness( rootLiveSet );
738 for( int i = 0; i < fn.numNext(); i++ ) {
739 FlatNode nn = fn.getNext( i );
741 if( !visited.contains( nn ) ) {
742 flatNodesToVisit.add( nn );
749 private void notAvailableForward( FlatMethod fm ) {
751 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
752 flatNodesToVisit.add( fm );
754 while( !flatNodesToVisit.isEmpty() ) {
755 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
756 flatNodesToVisit.remove( fn );
758 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
759 assert seseStack != null;
761 Set<TempDescriptor> prev = notAvailableResults.get( fn );
763 Set<TempDescriptor> curr = new HashSet<TempDescriptor>();
764 for( int i = 0; i < fn.numPrev(); i++ ) {
765 FlatNode nn = fn.getPrev( i );
766 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
767 if( notAvailIn != null ) {
768 curr.addAll( notAvailIn );
772 if( !seseStack.empty() ) {
773 notAvailable_nodeActions( fn, curr, seseStack.peek() );
776 // if a new result, schedule forward nodes for analysis
777 if( !curr.equals( prev ) ) {
778 notAvailableResults.put( fn, curr );
780 for( int i = 0; i < fn.numNext(); i++ ) {
781 FlatNode nn = fn.getNext( i );
782 flatNodesToVisit.add( nn );
788 private void notAvailable_nodeActions( FlatNode fn,
789 Set<TempDescriptor> notAvailSet,
790 FlatSESEEnterNode currentSESE ) {
792 // any temps that are removed from the not available set
793 // at this node should be marked in this node's code plan
794 // as temps to be grabbed at runtime!
796 switch( fn.kind() ) {
798 case FKind.FlatSESEEnterNode: {
799 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
800 assert fsen.equals( currentSESE );
804 case FKind.FlatSESEExitNode: {
805 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
806 FlatSESEEnterNode fsen = fsexn.getFlatEnter();
807 assert currentSESE.getChildren().contains( fsen );
809 Set<TempDescriptor> liveTemps = livenessRootView.get( fn );
810 assert liveTemps != null;
812 notAvailSet.addAll( liveTemps );
815 case FKind.FlatOpNode: {
816 FlatOpNode fon = (FlatOpNode) fn;
818 if( fon.getOp().getOp() == Operation.ASSIGN ) {
819 TempDescriptor lhs = fon.getDest();
820 TempDescriptor rhs = fon.getLeft();
822 // copy makes lhs same availability as rhs
823 if( notAvailSet.contains( rhs ) ) {
824 notAvailSet.add( lhs );
826 notAvailSet.remove( lhs );
829 // only break if this is an ASSIGN op node,
830 // otherwise fall through to default case
835 // note that FlatOpNode's that aren't ASSIGN
836 // fall through to this default case
838 TempDescriptor [] writeTemps = fn.writesTemps();
839 for( int i = 0; i < writeTemps.length; i++ ) {
840 TempDescriptor wTemp = writeTemps[i];
841 notAvailSet.remove( wTemp );
843 TempDescriptor [] readTemps = fn.readsTemps();
844 for( int i = 0; i < readTemps.length; i++ ) {
845 TempDescriptor rTemp = readTemps[i];
846 notAvailSet.remove( rTemp );
848 // if this variable has exactly one source, potentially
849 // get other things from this source as well
850 VarSrcTokTable vstTable = variableResults.get( fn );
853 vstTable.getRefVarSrcType( rTemp,
855 currentSESE.getParent() );
857 if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
859 VariableSourceToken vst = vstTable.get( rTemp ).iterator().next();
861 Iterator<VariableSourceToken> availItr = vstTable.get( vst.getSESE(),
865 // look through things that are also available from same source
866 while( availItr.hasNext() ) {
867 VariableSourceToken vstAlsoAvail = availItr.next();
869 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
870 while( refVarItr.hasNext() ) {
871 TempDescriptor refVarAlso = refVarItr.next();
873 // if a variable is available from the same source, AND it ALSO
874 // only comes from one statically known source, mark it available
875 Integer srcTypeAlso =
876 vstTable.getRefVarSrcType( refVarAlso,
878 currentSESE.getParent() );
879 if( srcTypeAlso.equals( VarSrcTokTable.SrcType_STATIC ) ) {
880 notAvailSet.remove( refVarAlso );
892 private void codePlansForward( FlatMethod fm ) {
894 // start from flat method top, visit every node in
895 // method exactly once
896 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
897 flatNodesToVisit.add( fm );
899 Set<FlatNode> visited = new HashSet<FlatNode>();
901 while( !flatNodesToVisit.isEmpty() ) {
902 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
903 FlatNode fn = fnItr.next();
905 flatNodesToVisit.remove( fn );
908 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
909 assert seseStack != null;
911 // use incoming results as "dot statement" or just
912 // before the current statement
913 VarSrcTokTable dotSTtable = new VarSrcTokTable();
914 for( int i = 0; i < fn.numPrev(); i++ ) {
915 FlatNode nn = fn.getPrev( i );
916 dotSTtable.merge( variableResults.get( nn ) );
919 // find dt-st notAvailableSet also
920 Set<TempDescriptor> dotSTnotAvailSet = new HashSet<TempDescriptor>();
921 for( int i = 0; i < fn.numPrev(); i++ ) {
922 FlatNode nn = fn.getPrev( i );
923 Set<TempDescriptor> notAvailIn = notAvailableResults.get( nn );
924 if( notAvailIn != null ) {
925 dotSTnotAvailSet.addAll( notAvailIn );
929 Set<TempDescriptor> dotSTlive = livenessRootView.get( fn );
931 if( !seseStack.empty() ) {
932 codePlans_nodeActions( fn,
940 for( int i = 0; i < fn.numNext(); i++ ) {
941 FlatNode nn = fn.getNext( i );
943 if( !visited.contains( nn ) ) {
944 flatNodesToVisit.add( nn );
950 private void codePlans_nodeActions( FlatNode fn,
951 Set<TempDescriptor> liveSetIn,
952 VarSrcTokTable vstTableIn,
953 Set<TempDescriptor> notAvailSetIn,
954 FlatSESEEnterNode currentSESE ) {
956 CodePlan plan = new CodePlan( currentSESE);
958 switch( fn.kind() ) {
960 case FKind.FlatSESEEnterNode: {
961 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
963 // track the source types of the in-var set so generated
964 // code at this SESE issue can compute the number of
965 // dependencies properly
966 Iterator<TempDescriptor> inVarItr = fsen.getInVarSet().iterator();
967 while( inVarItr.hasNext() ) {
968 TempDescriptor inVar = inVarItr.next();
970 vstTableIn.getRefVarSrcType( inVar,
974 // the current SESE needs a local space to track the dynamic
975 // variable and the child needs space in its SESE record
976 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
977 fsen.addDynamicInVar( inVar );
978 fsen.getParent().addDynamicVar( inVar );
980 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
981 fsen.addStaticInVar( inVar );
982 VariableSourceToken vst = vstTableIn.get( inVar ).iterator().next();
983 fsen.putStaticInVar2src( inVar, vst );
984 fsen.addStaticInVarSrc( new SESEandAgePair( vst.getSESE(),
990 assert srcType.equals( VarSrcTokTable.SrcType_READY );
991 fsen.addReadyInVar( inVar );
997 case FKind.FlatSESEExitNode: {
998 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
1001 case FKind.FlatOpNode: {
1002 FlatOpNode fon = (FlatOpNode) fn;
1004 if( fon.getOp().getOp() == Operation.ASSIGN ) {
1005 TempDescriptor lhs = fon.getDest();
1006 TempDescriptor rhs = fon.getLeft();
1008 // if this is an op node, don't stall, copy
1009 // source and delay until we need to use value
1011 // but check the source type of rhs variable
1012 // and if dynamic, lhs becomes dynamic, too,
1013 // and we need to keep dynamic sources during
1015 = vstTableIn.getRefVarSrcType( rhs,
1017 currentSESE.getParent() );
1019 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1020 plan.addDynAssign( lhs, rhs );
1021 currentSESE.addDynamicVar( lhs );
1022 currentSESE.addDynamicVar( rhs );
1025 // only break if this is an ASSIGN op node,
1026 // otherwise fall through to default case
1031 // note that FlatOpNode's that aren't ASSIGN
1032 // fall through to this default case
1035 // a node with no live set has nothing to stall for
1036 if( liveSetIn == null ) {
1040 TempDescriptor[] readarray = fn.readsTemps();
1041 for( int i = 0; i < readarray.length; i++ ) {
1042 TempDescriptor readtmp = readarray[i];
1044 // ignore temps that are definitely available
1045 // when considering to stall on it
1046 if( !notAvailSetIn.contains( readtmp ) ) {
1050 // check the source type of this variable
1052 = vstTableIn.getRefVarSrcType( readtmp,
1054 currentSESE.getParent() );
1056 if( srcType.equals( VarSrcTokTable.SrcType_DYNAMIC ) ) {
1057 // 1) It is not clear statically where this variable will
1058 // come from statically, so dynamically we must keep track
1059 // along various control paths, and therefore when we stall,
1060 // just stall for the exact thing we need and move on
1061 plan.addDynamicStall( readtmp );
1062 currentSESE.addDynamicVar( readtmp );
1064 } else if( srcType.equals( VarSrcTokTable.SrcType_STATIC ) ) {
1065 // 2) Single token/age pair: Stall for token/age pair, and copy
1066 // all live variables with same token/age pair at the same
1067 // time. This is the same stuff that the notavaialable analysis
1068 // marks as now available.
1070 VariableSourceToken vst = vstTableIn.get( readtmp ).iterator().next();
1072 Iterator<VariableSourceToken> availItr =
1073 vstTableIn.get( vst.getSESE(), vst.getAge() ).iterator();
1075 while( availItr.hasNext() ) {
1076 VariableSourceToken vstAlsoAvail = availItr.next();
1078 // only grab additional stuff that is live
1079 Set<TempDescriptor> copySet = new HashSet<TempDescriptor>();
1081 Iterator<TempDescriptor> refVarItr = vstAlsoAvail.getRefVars().iterator();
1082 while( refVarItr.hasNext() ) {
1083 TempDescriptor refVar = refVarItr.next();
1084 if( liveSetIn.contains( refVar ) ) {
1085 copySet.add( refVar );
1089 if( !copySet.isEmpty() ) {
1090 plan.addStall2CopySet( vstAlsoAvail, copySet );
1095 // the other case for srcs is READY from a parent, however
1096 // since we are only examining variables that come from
1097 // children tokens, this should never occur
1101 // assert that everything being stalled for is in the
1102 // "not available" set coming into this flat node and
1103 // that every VST identified is in the possible "stall set"
1104 // that represents VST's from children SESE's
1112 // identify sese-age pairs that are statically useful
1113 // and should have an associated SESE variable in code
1114 // JUST GET ALL SESE/AGE NAMES FOR NOW, PRUNE LATER,
1115 // AND ALWAYS GIVE NAMES TO PARENTS
1116 Set<VariableSourceToken> staticSet = vstTableIn.get();
1117 Iterator<VariableSourceToken> vstItr = staticSet.iterator();
1118 while( vstItr.hasNext() ) {
1119 VariableSourceToken vst = vstItr.next();
1121 FlatSESEEnterNode sese = currentSESE;
1122 while( sese != null ) {
1123 sese.addNeededStaticName(
1124 new SESEandAgePair( vst.getSESE(), vst.getAge() )
1126 sese.mustTrackAtLeastAge( vst.getAge() );
1128 sese = sese.getParent();
1133 codePlans.put( fn, plan );
1136 // if any variables at this-node-*dot* have a static source (exactly one vst)
1137 // but go to a dynamic source at next-node-*dot*, create a new IR graph
1138 // node on that edge to track the sources dynamically
1139 VarSrcTokTable thisVstTable = variableResults.get( fn );
1140 for( int i = 0; i < fn.numNext(); i++ ) {
1141 FlatNode nn = fn.getNext( i );
1142 VarSrcTokTable nextVstTable = variableResults.get( nn );
1143 Set<TempDescriptor> nextLiveIn = livenessRootView.get( nn );
1145 // the table can be null if it is one of the few IR nodes
1146 // completely outside of the root SESE scope
1147 if( nextVstTable != null && nextLiveIn != null ) {
1149 Hashtable<TempDescriptor, VariableSourceToken> static2dynamicSet =
1150 thisVstTable.getStatic2DynamicSet( nextVstTable, nextLiveIn );
1152 if( !static2dynamicSet.isEmpty() ) {
1154 // either add these results to partial fixed-point result
1155 // or make a new one if we haven't made any here yet
1156 FlatEdge fe = new FlatEdge( fn, nn );
1157 FlatWriteDynamicVarNode fwdvn = wdvNodesToSpliceIn.get( fe );
1159 if( fwdvn == null ) {
1160 fwdvn = new FlatWriteDynamicVarNode( fn,
1165 wdvNodesToSpliceIn.put( fe, fwdvn );
1167 fwdvn.addMoreVar2Src( static2dynamicSet );