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 SESENode rootTree;
21 private FlatSESEEnterNode rootSESE;
22 private FlatSESEExitNode rootExit;
24 private Hashtable< FlatNode, Stack<FlatSESEEnterNode> > seseStacks;
25 private Hashtable< FlatNode, Set<TempDescriptor> > livenessResults;
26 private Hashtable< FlatNode, VarSrcTokTable > variableResults;
29 public MLPAnalysis( State state,
32 OwnershipAnalysis ownAnalysis
35 double timeStartAnalysis = (double) System.nanoTime();
39 this.callGraph = callGraph;
40 this.ownAnalysis = ownAnalysis;
42 // initialize analysis data structures
43 seseStacks = new Hashtable< FlatNode, Stack<FlatSESEEnterNode> >();
44 livenessResults = new Hashtable< FlatNode, Set<TempDescriptor> >();
45 variableResults = new Hashtable< FlatNode, VarSrcTokTable >();
47 // build an implicit root SESE to wrap contents of main method
48 rootTree = new SESENode( "root" );
49 rootSESE = new FlatSESEEnterNode( rootTree );
50 rootExit = new FlatSESEExitNode ( rootTree );
51 rootSESE.setFlatExit ( rootExit );
52 rootExit.setFlatEnter( rootSESE );
56 // run analysis on each method that is actually called
57 // reachability analysis already computed this so reuse
58 Iterator<Descriptor> methItr = ownAnalysis.descriptorsToAnalyze.iterator();
59 while( methItr.hasNext() ) {
60 Descriptor d = methItr.next();
63 if( d instanceof MethodDescriptor ) {
64 fm = state.getMethodFlat( (MethodDescriptor) d);
66 assert d instanceof TaskDescriptor;
67 fm = state.getMethodFlat( (TaskDescriptor) d);
70 // find every SESE from methods that may be called
71 // and organize them into roots and children
72 buildForestForward( fm );
74 if( state.MLPDEBUG ) {
81 livenessAnalysisBackward( rootSESE );
85 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
86 while( methItr.hasNext() ) {
87 Descriptor d = methItr.next();
90 if( d instanceof MethodDescriptor ) {
91 fm = state.getMethodFlat( (MethodDescriptor) d);
93 assert d instanceof TaskDescriptor;
94 fm = state.getMethodFlat( (TaskDescriptor) d);
97 // starting from roots do a forward, fixed-point
98 // variable analysis for refinement and stalls
99 variableAnalysisForward( fm );
104 methItr = ownAnalysis.descriptorsToAnalyze.iterator();
105 while( methItr.hasNext() ) {
106 Descriptor d = methItr.next();
108 FlatMethod fm = state.getMethodFlat( d );
110 computeStallsForward( fm );
114 double timeEndAnalysis = (double) System.nanoTime();
115 double dt = (timeEndAnalysis - timeStartAnalysis)/(Math.pow( 10.0, 9.0 ) );
116 String treport = String.format( "The mlp analysis took %.3f sec.", dt );
117 System.out.println( treport );
120 private void buildForestForward( FlatMethod fm ) {
122 // start from flat method top, visit every node in
123 // method exactly once, find SESEs and remember
124 // roots and child relationships
125 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
126 flatNodesToVisit.add( fm );
128 Set<FlatNode> visited = new HashSet<FlatNode>();
130 Stack<FlatSESEEnterNode> seseStackFirst = new Stack<FlatSESEEnterNode>();
131 seseStackFirst.push( rootSESE );
132 seseStacks.put( fm, seseStackFirst );
134 while( !flatNodesToVisit.isEmpty() ) {
135 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
136 FlatNode fn = fnItr.next();
138 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
139 assert seseStack != null;
141 flatNodesToVisit.remove( fn );
144 buildForest_nodeActions( fn, seseStack );
146 for( int i = 0; i < fn.numNext(); i++ ) {
147 FlatNode nn = fn.getNext( i );
149 if( !visited.contains( nn ) ) {
150 flatNodesToVisit.add( nn );
152 // clone stack and send along each analysis path
153 seseStacks.put( nn, (Stack<FlatSESEEnterNode>)seseStack.clone() );
159 private void buildForest_nodeActions( FlatNode fn,
160 Stack<FlatSESEEnterNode> seseStack ) {
161 switch( fn.kind() ) {
163 case FKind.FlatSESEEnterNode: {
164 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
165 assert !seseStack.empty();
166 seseStack.peek().addChild( fsen );
167 seseStack.push( fsen );
170 case FKind.FlatSESEExitNode: {
171 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
172 assert !seseStack.empty();
173 FlatSESEEnterNode fsen = seseStack.pop();
176 case FKind.FlatReturnNode: {
177 FlatReturnNode frn = (FlatReturnNode) fn;
178 if( !seseStack.empty() &&
179 !seseStack.peek().equals( rootSESE ) ) {
180 throw new Error( "Error: return statement enclosed within "+seseStack.peek() );
187 private void printSESEForest() {
188 // our forest is actually a tree now that
189 // there is an implicit root SESE
190 printSESETree( rootSESE, 0 );
191 System.out.println( "" );
194 private void printSESETree( FlatSESEEnterNode fsen, int depth ) {
195 for( int i = 0; i < depth; ++i ) {
196 System.out.print( " " );
198 System.out.println( fsen.getPrettyIdentifier() );
200 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
201 while( childItr.hasNext() ) {
202 FlatSESEEnterNode fsenChild = childItr.next();
203 printSESETree( fsenChild, depth + 1 );
208 private void livenessAnalysisBackward( FlatSESEEnterNode fsen ) {
210 // post-order traversal, so do children first
211 Iterator<FlatSESEEnterNode> childItr = fsen.getChildren().iterator();
212 while( childItr.hasNext() ) {
213 FlatSESEEnterNode fsenChild = childItr.next();
214 livenessAnalysisBackward( fsenChild );
217 // start from an SESE exit, visit nodes in reverse up to
218 // SESE enter in a fixed-point scheme, where children SESEs
219 // should already be analyzed and therefore can be skipped
220 // because child SESE enter node has all necessary info
221 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
222 FlatSESEExitNode fsexn = fsen.getFlatExit();
223 flatNodesToVisit.add( fsexn );
225 while( !flatNodesToVisit.isEmpty() ) {
226 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
227 flatNodesToVisit.remove( fn );
229 Set<TempDescriptor> prev = livenessResults.get( fn );
231 // merge sets from control flow joins
232 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
233 for( int i = 0; i < fn.numNext(); i++ ) {
234 FlatNode nn = fn.getNext( i );
235 Set<TempDescriptor> s = livenessResults.get( nn );
241 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen );
243 // if a new result, schedule backward nodes for analysis
244 if( !curr.equals( prev ) ) {
246 livenessResults.put( fn, curr );
248 // don't flow backwards past current SESE enter
249 if( !fn.equals( fsen ) ) {
250 for( int i = 0; i < fn.numPrev(); i++ ) {
251 FlatNode nn = fn.getPrev( i );
252 flatNodesToVisit.add( nn );
258 Set<TempDescriptor> s = livenessResults.get( fsen );
260 fsen.addInVarSet( s );
263 if( state.MLPDEBUG ) {
264 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
265 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
266 while( tItr.hasNext() ) {
267 System.out.println( " "+tItr.next() );
269 System.out.println( "" );
273 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
274 Set<TempDescriptor> liveIn,
275 FlatSESEEnterNode currentSESE ) {
276 switch( fn.kind() ) {
279 // handle effects of statement in reverse, writes then reads
280 TempDescriptor [] writeTemps = fn.writesTemps();
281 for( int i = 0; i < writeTemps.length; ++i ) {
282 liveIn.remove( writeTemps[i] );
285 TempDescriptor [] readTemps = fn.readsTemps();
286 for( int i = 0; i < readTemps.length; ++i ) {
287 liveIn.add( readTemps[i] );
297 private void variableAnalysisForward( FlatMethod fm ) {
299 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
300 flatNodesToVisit.add( fm );
302 while( !flatNodesToVisit.isEmpty() ) {
303 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
304 flatNodesToVisit.remove( fn );
306 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
307 assert seseStack != null;
309 VarSrcTokTable prev = variableResults.get( fn );
311 // merge sets from control flow joins
312 VarSrcTokTable inUnion = new VarSrcTokTable();
313 for( int i = 0; i < fn.numPrev(); i++ ) {
314 FlatNode nn = fn.getPrev( i );
315 inUnion.merge( variableResults.get( nn ) );
318 VarSrcTokTable curr = variable_nodeActions( fn, inUnion, seseStack.peek() );
320 // if a new result, schedule forward nodes for analysis
321 if( !curr.equals( prev ) ) {
323 variableResults.put( fn, curr );
325 for( int i = 0; i < fn.numNext(); i++ ) {
326 FlatNode nn = fn.getNext( i );
327 flatNodesToVisit.add( nn );
332 if( state.MLPDEBUG ) {
336 private VarSrcTokTable variable_nodeActions( FlatNode fn,
337 VarSrcTokTable vstTable,
338 FlatSESEEnterNode currentSESE ) {
339 switch( fn.kind() ) {
341 case FKind.FlatSESEEnterNode: {
342 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
344 if( fsen.equals( currentSESE ) ) {
345 vstTable.age( currentSESE );
349 case FKind.FlatSESEExitNode: {
350 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
352 vstTable.removeChildToks( currentSESE );
355 case FKind.FlatOpNode: {
356 FlatOpNode fon = (FlatOpNode) fn;
358 if( fon.getOp().getOp() == Operation.ASSIGN ) {
359 TempDescriptor lhs = fon.getDest();
360 TempDescriptor rhs = fon.getLeft();
362 vstTable.remove( lhs );
364 Iterator<VariableSourceToken> itr = vstTable.get( rhs ).iterator();
365 while( itr.hasNext() ) {
366 VariableSourceToken vst = itr.next();
368 vstTable.add( new VariableSourceToken( lhs,
376 // only break if this is an ASSIGN op node,
377 // otherwise fall through to default case
382 // note that FlatOpNode's that aren't ASSIGN
383 // fall through to this default case
385 TempDescriptor [] writeTemps = fn.writesTemps();
386 if( writeTemps.length > 0 ) {
387 assert writeTemps.length == 1;
389 vstTable.remove( writeTemps[0] );
391 vstTable.add( new VariableSourceToken( writeTemps[0],
406 private void computeStallsForward( FlatMethod fm ) {
408 // start from flat method top, visit every node in
409 // method exactly once
410 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
411 flatNodesToVisit.add( fm );
413 Set<FlatNode> visited = new HashSet<FlatNode>();
415 while( !flatNodesToVisit.isEmpty() ) {
416 Iterator<FlatNode> fnItr = flatNodesToVisit.iterator();
417 FlatNode fn = fnItr.next();
419 flatNodesToVisit.remove( fn );
422 Stack<FlatSESEEnterNode> seseStack = seseStacks.get( fn );
423 assert seseStack != null;
425 VarSrcTokTable vstTable = variableResults.get( fn );
427 computeStalls_nodeActions( fn, vstTable, seseStack.peek() );
429 for( int i = 0; i < fn.numNext(); i++ ) {
430 FlatNode nn = fn.getNext( i );
432 if( !visited.contains( nn ) ) {
433 flatNodesToVisit.add( nn );
439 private void computeStalls_nodeActions( FlatNode fn,
440 VarSrcTokTable vstTable,
441 FlatSESEEnterNode currentSESE ) {
442 switch( fn.kind() ) {
444 case FKind.FlatSESEEnterNode: {
445 FlatSESEEnterNode fsen = (FlatSESEEnterNode) fn;
448 case FKind.FlatSESEExitNode: {
449 FlatSESEExitNode fsexn = (FlatSESEExitNode) fn;
453 Set<VariableSourceToken> stallSet =
454 vstTable.getStallSet( currentSESE );
456 System.out.println( fn+" should stall on\n "+stallSet+"\n" );