| /********************************************************************** |
| * 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); |
| } |
| |
| } |
| } |