blob: 1a484bf4462a2f0cf8ccf453a19dba3baff3b86b [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);
}
}
}