blob: 50d114d6d1b5803636a86e3b69124fb7820f2e60 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2006 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ptp.pldt.openmp.analysis.ompcfg.factory;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Stack;
import org.eclipse.ptp.pldt.openmp.analysis.PAST.PASTOMPPragma;
import org.eclipse.ptp.pldt.openmp.analysis.ompcfg.OMPCFG;
import org.eclipse.ptp.pldt.openmp.analysis.ompcfg.OMPCFGNode;
import org.eclipse.ptp.pldt.openmp.analysis.ompcfg.OMPDFS;
import org.eclipse.ptp.pldt.openmp.analysis.ompcfg.OMPPragmaNode;
/**
* Main Algorithm -
*
* Given: the start node of a control flow graph (OMPCFG)
* Output: a set of barrier phases
*
* 1) Start the algorithm using the start node of the cfg
* 2) For each barrier reached by a DFS, said barrier neither prior processed
* nor on the stack, push onto stack, and start fresh DFS on new barrier
* 3) For each node encountered
* a) if node is in a phase having its initial barrier match with top barrier
* on the stack, add all nodes after that top barrier to that phase.
* b) if node is a barrier, build phase, add nodes on stack from penultimate
* barrier
* 4) When a DFS completes, pop the stack
* 5) Terminate when the stack is empty
*
*/
public class PhaseAnalysisFactory
{
protected OMPCFG cfg_ = null;
protected OMPCFGNode termNode_ = null;
protected Stack barrierStack_ = new Stack(); // of DFSWalk's
protected HashSet finishedBarriers_ = new HashSet(); // of barriers that are finished being
// traversed from
protected LinkedList phases_ = new LinkedList(); // of PhaseConcurrencyAnalysis's
// A common search we do is, for a given node, and a given barrier, find all
// phases that
// a) contain that node
// b) have that barrier as the starting barrier of the phase
// Solution: map each node to a list of phases to which it belongs.
// The list should be sparse, for filtering out the phases that
// begin with a particular barrier should be inexpensive.
protected Hashtable nodeToPhases_ = new Hashtable();
/**
* PhaseAnalysisFactory - Constructor
* @param cfg - OMPCFG
*/
public PhaseAnalysisFactory(OMPCFG cfg)
{
cfg_ = cfg;
termNode_ = cfg_.getTermNode();
}
public void buildPhases()
{
// Set up the first statement
OMPCFGNode node = cfg_.getRoot();
if (!(node instanceof OMPPragmaNode)) return; // required
DFSWalk pc = new DFSWalk((OMPPragmaNode)node);
barrierStack_.push(pc);
pc.trigger();
}
/**
* findPhase - find a specified phase and add it
* @param bNode - OMPPragmaNode
* @param eNode - OMPPragmaNode
* @param addNew - boolean
* @return PhaseConcurrencyAnalysis
*/
protected PhaseConcurrencyAnalysis findPhase(OMPPragmaNode bNode, OMPPragmaNode eNode, boolean addNew)
{
// Find the phase that starts and ends with these TODO: make more efficient
for(Iterator i=phases_.iterator(); i.hasNext();) {
PhaseConcurrencyAnalysis phase = (PhaseConcurrencyAnalysis)i.next();
if (phase.getBeginNode()==bNode && phase.getEndNode()==eNode)
return phase;
}
if (!addNew) return null;
PhaseConcurrencyAnalysis phase = new PhaseConcurrencyAnalysis(bNode, eNode);
phases_.add(phase);
return phase;
}
/**
* addNodesToPhase - add a list of nodes to a specific phase
* @param phase - PhaseConcurrencyAnalysis
* @param nodes - OMPCFGNode []
*/
protected void addNodesToPhase(PhaseConcurrencyAnalysis phase, OMPCFGNode [] nodes)
{
for(int i=0; i<nodes.length; i++) {
phase.add(nodes[i]);
mapNodeToPhase(nodes[i], phase);
}
}
protected boolean isFinished(OMPPragmaNode pNode)
{
return finishedBarriers_.contains(pNode);
}
protected boolean isOnBarrierStack(OMPPragmaNode pNode)
{
for(Iterator i=barrierStack_.iterator(); i.hasNext();) {
DFSWalk dw = (DFSWalk)i.next();
if (dw.getPragmaNode()==pNode) return true;
}
return false;
}
protected LinkedList memberPhases(OMPCFGNode node)
{
return (LinkedList)nodeToPhases_.get(node);
}
/**
* mapNodeToPhase - map a given node to a given phase in the node-phase map
* @param node - OMPCFGNode
* @param phase - PhaseConcurrencyAnalysis
*/
protected void mapNodeToPhase(OMPCFGNode node, PhaseConcurrencyAnalysis phase)
{
LinkedList l = (LinkedList)nodeToPhases_.get(node);
if (l==null) {
l= new LinkedList();
nodeToPhases_.put(node, l);
}
if (!l.contains(phase))
l.add(phase);
}
/**
* getPhases - produce a list of all phases produced from this analysis
* @return PhaseConcurrencyAnalysis []
*/
public PhaseConcurrencyAnalysis [] getPhases()
{
PhaseConcurrencyAnalysis [] l = new PhaseConcurrencyAnalysis[phases_.size()];
int count = 0;
for(Iterator i=phases_.iterator(); i.hasNext();)
l[count++] = (PhaseConcurrencyAnalysis)i.next();
return l;
}
//*************************************************************************
// DFSWalk
//*************************************************************************
protected class DFSWalk extends OMPDFS
{
protected OMPPragmaNode phaseBeginNode_ = null;
public DFSWalk(OMPPragmaNode phaseBeginNode)
{
super(phaseBeginNode);
phaseBeginNode_ = phaseBeginNode;
}
public OMPPragmaNode getPragmaNode()
{
return phaseBeginNode_;
}
/**
* trigger - begin the process of walking the graph
*
*/
public void trigger()
{
this.startWalking();
}
/**
* visit - visit method - what the user usually overrides
* @param node - OMPCFGNode
* @return int (see OMPDFS codes)
*/
public int visit(OMPCFGNode node)
{
if (node instanceof OMPPragmaNode) {
OMPPragmaNode pragmaNode = (OMPPragmaNode)node;
if (pragmaNode.getPragma()!=null && pragmaNode.getPragma().getOMPType()!=PASTOMPPragma.OmpBarrier)
return OMPDFS.CONTINUE;
// If at beginning of stack again, keep moving on
if (getNodeStackSize()==1) return OMPDFS.CONTINUE;
// If necessary, create a new phase and add to list of phases
PhaseConcurrencyAnalysis phase = findPhase(phaseBeginNode_, pragmaNode, true);
addNodesToPhase(phase, getNodeStack());
// If barrier is completed or is on stack, we skip searching forward
if (isFinished(pragmaNode) || isOnBarrierStack(pragmaNode))
return OMPDFS.SKIP;
// Create a new walk to the next segments - increase the stack
// NOTE: we may have to skip the followin for implict barrier
DFSWalk pc = new DFSWalk(pragmaNode);
barrierStack_.push(pc);
pc.trigger();
// above finished walking, pop the stack, and skip on this level
barrierStack_.pop();
return OMPDFS.SKIP;
}
else if (node==termNode_) { // this is an implicit barrier, but not further dfs
if (getNodeStackSize()==1) return OMPDFS.CONTINUE;
return OMPDFS.CONTINUE;
}
// For each visited successor node, add node stack to all phases the successor
// belongs to, said successor phase beginning with phaseBeginNode_
// Note: we should not bother with phases that begin with other than phaseBeginNode_ -
// as then we would have to account for partial paths from other such phases,
// which we do not have (we glom all nodes together, no paths). That was why
// we do fresh searches starting at new barriers.
OMPCFGNode [] nodes = node.getOutNodes();
for(int i=0; i<nodes.length; i++) {
if (isVisited(nodes[i])) {
LinkedList l = memberPhases(nodes[i]);
OMPCFGNode [] nodeStack = getNodeStack();
Object [] listArray = l.toArray(); // safer to use this, l may get modified
for(int j=0; j<listArray.length; j++) {
PhaseConcurrencyAnalysis phase = (PhaseConcurrencyAnalysis)listArray[j];
if (phase.getBeginNode()==phaseBeginNode_)
addNodesToPhase(phase, nodeStack);
}
}
}
return OMPDFS.CONTINUE;
}
/**
* atStartNode - check if we are at the 1st node of the search
* @param node
* @return
*/
protected boolean atStartNode(OMPCFGNode node)
{
return (node==phaseBeginNode_ && getNodeStackSize()==1);
}
}
}