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 Set<FlatSESEEnterNode> seseRoots;
21 private SESENode rootTree;
22 private FlatSESEEnterNode rootSESE;
23 private FlatSESEExitNode rootExit;
25 private Hashtable< FlatNode, Stack<FlatSESEEnterNode> > seseStacks;
26 private Hashtable< FlatNode, VarSrcTokTable > livenessResults;
27 private Hashtable< FlatNode, VarSrcTokTable > variableResults;
30 public MLPAnalysis( State state,
33 OwnershipAnalysis ownAnalysis
36 double timeStartAnalysis = (double) System.nanoTime();
40 this.callGraph = callGraph;
41 this.ownAnalysis = ownAnalysis;
43 // initialize analysis data structures
44 seseRoots = new HashSet<FlatSESEEnterNode>();
45 seseStacks = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
46 livenessResults = new Hashtable< FlatNode, VarSrcTokTable >();
47 variableResults = new Hashtable< FlatNode, VarSrcTokTable >();
49 // build an implicit root SESE to wrap contents of main method
51 rootTree = new SESENode( "root" );
52 rootSESE = new FlatSESEEnterNode( rootTree );
53 rootExit = new FlatSESEExitNode ( rootTree );
54 rootSESE.setFlatExit ( rootExit );
55 rootExit.setFlatEnter( rootSESE );
56 seseRoots.add( rootSESE );
59 // run analysis on each method that is actually called
60 // reachability analysis already computed this so reuse
61 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
62 while( methItr.hasNext() ) {
63 Descriptor d = methItr.next();
66 if( d instanceof MethodDescriptor ) {
67 fm = state.getMethodFlat( (MethodDescriptor) d);
69 assert d instanceof TaskDescriptor;
70 fm = state.getMethodFlat( (TaskDescriptor) d);
73 // find every SESE from methods that may be called
74 // and organize them into roots and children
75 buildForestForward( fm );
77 if( state.MLPDEBUG ) {
82 Iterator<FlatSESEEnterNode> seseItr = seseRoots.iterator();
83 while( seseItr.hasNext() ) {
84 FlatSESEEnterNode fsen = seseItr.next();
86 // do a post-order traversal of the forest so that
87 // a child is analyzed before a parent. Start from
88 // SESE's exit and do a backward data-flow analysis
89 // for the source of variables
90 livenessAnalysisBackward( fsen );
94 seseItr = seseRoots.iterator();
95 while( seseItr.hasNext() ) {
96 FlatSESEEnterNode fsen = seseItr.next();
98 // starting from roots do a forward, fixed-point
99 // variable analysis for refinement and stalls
100 variableAnalysisForward( fsen );
104 double timeEndAnalysis = (double) System.nanoTime();
105 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
106 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
107 System.out.println( treport );
110 private void buildForestForward( FlatMethod fm ) {
112 // start from flat method top, visit every node in
113 // method exactly once, find SESEs and remember
114 // roots and child relationships
115 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
116 flatNodesToVisit.add( fm );
118 Set<FlatNode> visited = new HashSet<FlatNode>();
120 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
121 //seseStackFirst.push( rootSESE );
122 seseStacks.put( fm, seseStackFirst );
124 while( !flatNodesToVisit.isEmpty() ) {
125 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
126 FlatNode fn = fnItr.next();
128 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
129 assert seseStack != null;
131 flatNodesToVisit.remove( fn );
134 buildForest_nodeActions( fn, seseStack );
136 for( int i = 0; i < fn.numNext(); i++ ) {
137 FlatNode nn = fn.getNext( i );
139 if( !visited.contains( nn ) ) {
140 flatNodesToVisit.add( nn );
142 // clone stack and send along each analysis path
143 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
149 private void buildForest_nodeActions( FlatNode fn,
150 Stack<FlatSESEEnterNode> seseStack ) {
151 switch( fn.kind() ) {
153 case FKind.FlatSESEEnterNode: {
154 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
156 if( seseStack.empty() ) {
157 seseRoots.add( fsen );
159 seseStack.peek().addChild( fsen );
161 seseStack.push( fsen );
164 case FKind.FlatSESEExitNode: {
165 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
167 assert !seseStack.empty();
168 FlatSESEEnterNode fsen = seseStack.pop();
171 case FKind.FlatReturnNode: {
172 FlatReturnNode frn = (FlatReturnNode) fn;
173 if( !seseStack.empty() ) {
174 throw new Error( "Error: return statement enclosed within "+seseStack.peek() );
181 private void printSESEForest() {
182 // we are assuming an implicit root SESE in the main method
183 // so assert that our forest is actually a tree
184 assert seseRoots.size() == 1;
186 System.out.println( "SESE Forest:" );
187 Iterator<FlatSESEEnterNode> seseItr = seseRoots.iterator();
188 while( seseItr.hasNext() ) {
189 FlatSESEEnterNode fsen = seseItr.next();
190 printSESETree( fsen, 0 );
191 System.out.println( "" );
195 private void printSESETree( FlatSESEEnterNode fsen, int depth ) {
196 for( int i = 0; i < depth; ++i ) {
197 System.out.print( " " );
199 System.out.println( fsen.getPrettyIdentifier() );
201 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
202 while( childItr.hasNext() ) {
203 FlatSESEEnterNode fsenChild = childItr.next();
204 printSESETree( fsenChild, depth + 1 );
209 private void livenessAnalysisBackward( FlatSESEEnterNode fsen ) {
211 // post-order traversal, so do children first
212 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
213 while( childItr.hasNext() ) {
214 FlatSESEEnterNode fsenChild = childItr.next();
215 livenessAnalysisBackward( fsenChild );
218 // start from an SESE exit, visit nodes in reverse up to
219 // SESE enter in a fixed-point scheme, where children SESEs
220 // should already be analyzed and therefore can be skipped
221 // because child SESE enter node has all necessary info
222 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
223 FlatSESEExitNode fsexn = fsen.getFlatExit();
224 flatNodesToVisit.add( fsexn );
226 for( int i = 0; i < fsexn.numPrev(); i++ ) {
227 FlatNode nn = fsexn.getPrev( i );
228 flatNodesToVisit.add( nn );
232 while( !flatNodesToVisit.isEmpty() ) {
233 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
234 flatNodesToVisit.remove( fn );
237 if( fn.kind() == FKind.FlatSESEExitNode ) {
238 fn = ((FlatSESEExitNode)fn).getFlatEnter();
242 VarSrcTokTable prev = livenessResults.get( fn );
244 // merge sets from control flow joins
245 VarSrcTokTable inUnion = new VarSrcTokTable();
246 for( int i = 0; i < fn.numNext(); i++ ) {
247 FlatNode nn = fn.getNext( i );
248 inUnion.merge( livenessResults.get( nn ) );
251 VarSrcTokTable curr = liveness_nodeActions( fn, inUnion, fsen );
253 // if a new result, schedule backward nodes for analysis
254 if( !curr.equals( prev ) ) {
256 livenessResults.put( fn, curr );
258 // don't flow backwards past current SESE enter
259 if( !fn.equals( fsen ) ) {
260 for( int i = 0; i < fn.numPrev(); i++ ) {
261 FlatNode nn = fn.getPrev( i );
262 flatNodesToVisit.add( nn );
268 fsen.addInVarSet( livenessResults.get( fsen ).get() );
270 if( state.MLPDEBUG ) {
271 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
272 Iterator<VariableSourceToken> tItr = fsen.getInVarSet().iterator();
273 while( tItr.hasNext() ) {
274 System.out.println( " "+tItr.next() );
277 System.out.println( "and out-set:" );
278 tItr = fsen.getOutVarSet().iterator();
279 while( tItr.hasNext() ) {
280 System.out.println( " "+tItr.next() );
283 System.out.println( "" );
287 private VarSrcTokTable liveness_nodeActions( FlatNode fn,
288 VarSrcTokTable vstTable,
289 FlatSESEEnterNode currentSESE ) {
290 switch( fn.kind() ) {
292 case FKind.FlatSESEEnterNode: {
293 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
295 // only age if this is a child SESE, not the current
296 if( !fsen.equals( currentSESE ) ) {
297 vstTable = vstTable.age( currentSESE );
302 // handle effects of statement in reverse, writes then reads
303 TempDescriptor [] writeTemps = fn.writesTemps();
304 for( int i = 0; i < writeTemps.length; ++i ) {
305 vstTable.remove( writeTemps[i] );
306 currentSESE.addOutVar( new VariableSourceToken( currentSESE,
308 new Integer( 0 ) ) );
311 TempDescriptor [] readTemps = fn.readsTemps();
312 for( int i = 0; i < readTemps.length; ++i ) {
313 vstTable.add( new VariableSourceToken( currentSESE,
315 new Integer( 0 ) ) );
325 private void variableAnalysisForward( FlatSESEEnterNode fsen ) {
327 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
328 flatNodesToVisit.add( fsen );
330 while( !flatNodesToVisit.isEmpty() ) {
331 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
332 flatNodesToVisit.remove( fn );
334 VarSrcTokTable prev = variableResults.get( fn );
336 // merge sets from control flow joins
337 VarSrcTokTable inUnion = new VarSrcTokTable();
338 for( int i = 0; i < fn.numPrev(); i++ ) {
339 FlatNode nn = fn.getPrev( i );
340 inUnion.merge( variableResults.get( nn ) );
343 VarSrcTokTable curr = variable_nodeActions( fn, inUnion, fsen );
345 // if a new result, schedule backward nodes for analysis
346 if( !curr.equals( prev ) ) {
348 variableResults.put( fn, curr );
350 // don't flow backwards past SESE enter
351 if( !fn.equals( fsen ) ) {
352 for( int i = 0; i < fn.numPrev(); i++ ) {
353 FlatNode nn = fn.getPrev( i );
354 flatNodesToVisit.add( nn );
360 fsen.addInVarSet( variableResults.get( fsen ).get() );
362 if( state.MLPDEBUG ) {
363 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
364 Iterator<VariableSourceToken> tItr = fsen.getInVarSet().iterator();
365 while( tItr.hasNext() ) {
366 System.out.println( " "+tItr.next() );
368 System.out.println( "and out-set:" );
369 tItr = fsen.getOutVarSet().iterator();
370 while( tItr.hasNext() ) {
371 System.out.println( " "+tItr.next() );
373 System.out.println( "" );
377 private VarSrcTokTable variable_nodeActions( FlatNode fn,
378 VarSrcTokTable vstTable,
379 FlatSESEEnterNode currentSESE ) {
380 switch( fn.kind() ) {