blob: 6bef4eacdc18c2977e02f75cff6606a79d782746 [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.ArrayList;
import java.util.BitSet;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.ptp.pldt.openmp.analysis.PAST.PASTOMPPragma;
import org.eclipse.ptp.pldt.openmp.analysis.ompcfg.OMPBasicBlock;
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.OMPExpressionBlock;
import org.eclipse.ptp.pldt.openmp.analysis.ompcfg.OMPPragmaNode;
/**
* Builds the concurrency map and provides access to it
*
* @author pazel
*
*/
public class RegionConcurrencyMap
{
protected RegionConcurrencyAnalysis region_ = null;
protected OMPCFG cfg_ = null;
protected PhaseConcurrencyAnalysis[] phases_ = null;
// The actual map
protected ArrayList indexMap_ = new ArrayList(); // index->stmt
protected Hashtable stmtMap_ = new Hashtable(); // stmt->index
// stmt to BitSet, representing all statments concurrent to stmt
protected Hashtable concurrencyMap_ = new Hashtable();
// Used in each phase process to list all nodes found
protected LinkedList phaseStmts_ = new LinkedList();
// Some sub-regions need to exclude within themselves. To help with this,
// we build a iastnode-->OMPPragmaNode hashmap, used by the second part of processConcurrency
protected Hashtable exclusionMap_ = new Hashtable();
/**
* RegionConcurrencyMap - constructor
*
* @param component
* - RegionConcurrencyAnalysis
*/
public RegionConcurrencyMap(RegionConcurrencyAnalysis region)
{
region_ = region;
cfg_ = region_.getCFG();
phases_ = region_.getPhases();
}
/**
* buildMap - build the concurrencyMap_ and other artifacts for the map
*
*/
public void buildMap()
{
for (int i = 0; i < phases_.length; i++)
processPhase(phases_[i]);
}
/**
* processPhase - process given phase into the concurrency map
*
* @param phase
* - PhaseConcurrencyAnalysis
*/
protected void processPhase(PhaseConcurrencyAnalysis phase)
{
Set nodes = phase.getNodes(); // of OMPCFGNode's
phaseStmts_.clear();
exclusionMap_.clear();
OMPPragmaNode ePragma = null; // exclusion pragma
for (Iterator i = nodes.iterator(); i.hasNext();) {
OMPCFGNode node = (OMPCFGNode) i.next();
// Establish the exclusion context if any
ePragma = node.getPragmaContext();
if (ePragma != null && ePragma.getPragma() != null) {
int pType = ePragma.getPragma().getOMPType();
// if none of these situations, all the stmts in the node can execute concurrently to each other
// (note: if single and has barrier free path to self, stmts can execute concurrently to each other
if (!((pType == PASTOMPPragma.OmpSingle && !hasBarrierFreePathToSelf((OMPBasicBlock) node)) ||
pType == PASTOMPPragma.OmpMaster ||
pType == PASTOMPPragma.OmpOrdered ||
pType == PASTOMPPragma.OmpCritical || pType == PASTOMPPragma.OmpSection))
ePragma = null;
}
else
ePragma = null;
if (node instanceof OMPBasicBlock) {
LinkedList stmts = ((OMPBasicBlock) node).getFundamentals();
for (Iterator j = stmts.iterator(); j.hasNext();) {
IASTNode n = (IASTNode) j.next();
indexNode(n, ePragma);
}
indexNode(((OMPBasicBlock) node).getBranchingExpression(), ePragma);
}
else if (node instanceof OMPExpressionBlock) {
IASTExpression[] eList = ((OMPExpressionBlock) node).getExpressions();
for (int j = 0; j < eList.length; j++)
indexNode(eList[j], ePragma);
}
}
// Go though the list of phase nodes, and
// ASSUMING THEY ARE ALL CONCURRENT WITH EACH OTHER (will change later)
// make them all concurrent to each other
for (Iterator i = phaseStmts_.iterator(); i.hasNext();) {
IASTNode n = (IASTNode) i.next();
OMPPragmaNode ePragmaS = (OMPPragmaNode) exclusionMap_.get(n);
int nIndex = ((Integer) (stmtMap_.get(n))).intValue();
for (Iterator j = phaseStmts_.iterator(); j.hasNext();) {
IASTNode m = (IASTNode) j.next();
OMPPragmaNode ePragmaT = (OMPPragmaNode) exclusionMap_.get(m);
// stmts in the same exclusion cannot be concurrent
if (!(ePragmaT == ePragmaS && ePragmaT != null)) {
BitSet b = (BitSet) (concurrencyMap_.get(m));
b.set(nIndex);
}
}
}
}
/**
* indexNode - index a node if node not seen to this process
*
* @param n
* - IASTNode
*/
protected void indexNode(IASTNode n, OMPPragmaNode ePragma)
{
if (n == null)
return;
if (!stmtMap_.containsKey(n)) {
indexMap_.add(n);
stmtMap_.put(n, new Integer(indexMap_.indexOf(n)));
concurrencyMap_.put(n, new BitSet());
}
if (!phaseStmts_.contains(n))
phaseStmts_.add(n);
// Set up the exclusion map
if (ePragma != null && !exclusionMap_.contains(n))
exclusionMap_.put(n, ePragma);
}
/**
* getNodesConcurrentTo - get all nodes concurrent to given node
*
* @param node
* - IASTNode
* @return Set
*/
public Set getNodesConcurrentTo(IASTNode node)
{
BitSet b = (BitSet) concurrencyMap_.get(node);
if (b == null)
return null; // stmt never registered - ind. called for wrong component
HashSet ans = new HashSet();
for (int i = b.nextSetBit(0); i >= 0; i = b.nextSetBit(i + 1))
ans.add(indexMap_.get(i));
return ans;
}
private boolean hasBarrierFreePathToSelf(OMPBasicBlock singleBlock)
{
BarrierPathDFS dfs = new BarrierPathDFS(singleBlock);
dfs.startWalking();
return dfs.hasBarrierFreePath();
}
// -------------------------------------------------------------------------
// BarrierPathDFS - find barrier free path to pragma
// -------------------------------------------------------------------------
private class BarrierPathDFS extends OMPDFS
{
// find a barrier free path to this node
protected OMPPragmaNode target_ = null;
protected boolean barrierFreeExists_ = false;
public BarrierPathDFS(OMPBasicBlock block)
{
super(block);
target_ = block.getPragmaContext();
}
public boolean hasBarrierFreePath()
{
return barrierFreeExists_;
}
/**
* visit - visit method - what the user usually overrides
*
* @param node
* - OMPCFGNode
*/
public int visit(OMPCFGNode node)
{
if (node instanceof OMPPragmaNode) {
OMPPragmaNode thisNode = (OMPPragmaNode) node;
if (thisNode.isImplicitBarrier() || thisNode.getPragma().getOMPType() == PASTOMPPragma.OmpBarrier)
return SKIP;
else if (thisNode == target_) {
barrierFreeExists_ = true;
return ABORT;
}
}
return CONTINUE;
}
}
}