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, Set<TempDescriptor> > 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, Set<TempDescriptor> >();
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 Set<TempDescriptor> prev = livenessResults.get( fn );
244 // merge sets from control flow joins
245 Set<TempDescriptor> u = new HashSet<TempDescriptor>();
246 for( int i = 0; i < fn.numNext(); i++ ) {
247 FlatNode nn = fn.getNext( i );
248 Set<TempDescriptor> s = livenessResults.get( nn );
254 Set<TempDescriptor> curr = liveness_nodeActions( fn, u, fsen );
256 // if a new result, schedule backward nodes for analysis
257 if( !curr.equals( prev ) ) {
259 livenessResults.put( fn, curr );
261 // don't flow backwards past current SESE enter
262 if( !fn.equals( fsen ) ) {
263 for( int i = 0; i < fn.numPrev(); i++ ) {
264 FlatNode nn = fn.getPrev( i );
265 flatNodesToVisit.add( nn );
271 Set<TempDescriptor> s = livenessResults.get( fsen );
273 fsen.addInVarSet( s );
276 if( state.MLPDEBUG ) {
277 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
278 Iterator<TempDescriptor> tItr = fsen.getInVarSet().iterator();
279 while( tItr.hasNext() ) {
280 System.out.println( " "+tItr.next() );
283 System.out.println( "and out-set:" );
284 tItr = fsen.getOutVarSet().iterator();
285 while( tItr.hasNext() ) {
286 System.out.println( " "+tItr.next() );
289 System.out.println( "" );
293 private Set<TempDescriptor> liveness_nodeActions( FlatNode fn,
294 Set<TempDescriptor> liveIn,
295 FlatSESEEnterNode currentSESE ) {
296 switch( fn.kind() ) {
299 // handle effects of statement in reverse, writes then reads
300 TempDescriptor [] writeTemps = fn.writesTemps();
301 for( int i = 0; i < writeTemps.length; ++i ) {
302 liveIn.remove( writeTemps[i] );
305 TempDescriptor [] readTemps = fn.readsTemps();
306 for( int i = 0; i < readTemps.length; ++i ) {
307 liveIn.add( readTemps[i] );
317 private void variableAnalysisForward( FlatSESEEnterNode fsen ) {
319 Set<FlatNode> flatNodesToVisit = new HashSet<FlatNode>();
320 flatNodesToVisit.add( fsen );
322 while( !flatNodesToVisit.isEmpty() ) {
323 FlatNode fn = (FlatNode) flatNodesToVisit.iterator().next();
324 flatNodesToVisit.remove( fn );
326 VarSrcTokTable prev = variableResults.get( fn );
328 // merge sets from control flow joins
329 VarSrcTokTable inUnion = new VarSrcTokTable();
330 for( int i = 0; i < fn.numPrev(); i++ ) {
331 FlatNode nn = fn.getPrev( i );
332 inUnion.merge( variableResults.get( nn ) );
335 VarSrcTokTable curr = variable_nodeActions( fn, inUnion, fsen );
337 // if a new result, schedule backward nodes for analysis
338 if( !curr.equals( prev ) ) {
340 variableResults.put( fn, curr );
342 // don't flow backwards past SESE enter
343 if( !fn.equals( fsen ) ) {
344 for( int i = 0; i < fn.numPrev(); i++ ) {
345 FlatNode nn = fn.getPrev( i );
346 flatNodesToVisit.add( nn );
352 fsen.addInVarSet( variableResults.get( fsen ).get() );
354 if( state.MLPDEBUG ) {
355 System.out.println( "SESE "+fsen.getPrettyIdentifier()+" has in-set:" );
356 Iterator<VariableSourceToken> tItr = fsen.getInVarSet().iterator();
357 while( tItr.hasNext() ) {
358 System.out.println( " "+tItr.next() );
360 System.out.println( "and out-set:" );
361 tItr = fsen.getOutVarSet().iterator();
362 while( tItr.hasNext() ) {
363 System.out.println( " "+tItr.next() );
365 System.out.println( "" );
370 private VarSrcTokTable variable_nodeActions( FlatNode fn,
371 VarSrcTokTable vstTable,
372 FlatSESEEnterNode currentSESE ) {
373 switch( fn.kind() ) {