| /********************************************************************** |
| * Copyright (c) 2007,2011 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.mpi.analysis.analysis; |
| |
| import java.util.ArrayList; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Stack; |
| |
| import org.eclipse.cdt.core.dom.ast.IASTDoStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTFileLocation; |
| import org.eclipse.cdt.core.dom.ast.IASTForStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTIfStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTNode; |
| import org.eclipse.cdt.core.dom.ast.IASTNodeLocation; |
| import org.eclipse.cdt.core.dom.ast.IASTStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTWhileStatement; |
| import org.eclipse.cdt.internal.core.dom.parser.c.CASTCompoundStatement; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.ptp.pldt.common.Artifact; |
| import org.eclipse.ptp.pldt.common.util.SourceInfo; |
| import org.eclipse.ptp.pldt.mpi.analysis.analysis.BarrierExpression.BarrierExpressionOP; |
| import org.eclipse.ptp.pldt.mpi.analysis.analysis.BarrierTable.BarrierInfo; |
| import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.ICallGraph; |
| import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.ICallGraphNode; |
| import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.IControlFlowGraph; |
| import org.eclipse.ptp.pldt.mpi.analysis.internal.IDs; |
| import org.eclipse.ptp.pldt.mpi.analysis.messages.Messages; |
| import org.eclipse.ptp.pldt.mpi.analysis.popup.actions.ShowMatchSet; |
| |
| /** |
| * Determine matching of MPI barriers. Matching barriers belong to a |
| * "matching set." Matching barriers use the same MPI Communicator, and every |
| * task must encounter a barrier in the set in order to not have a deadlock. |
| * |
| * @author Beth Tibbitts (originally Yuan Zhang) |
| * |
| */ |
| public class MPIBarrierMatching { |
| protected ICallGraph cg_; |
| protected IControlFlowGraph cfg_; |
| protected MPICallGraphNode currentFunc_; |
| protected String currentComm_; |
| |
| protected Hashtable<BarrierExpression, List<BarrierExpression>> visited_; |
| protected BarrierTable barrierTable_; |
| protected List<ErrorMessage> barrierErrors_; |
| protected boolean error; |
| |
| protected int mv = 0; |
| protected int sv = 0; |
| private static final boolean traceOn = false; |
| |
| public MPIBarrierMatching(ICallGraph cg, BarrierTable table) { |
| cg_ = cg; |
| barrierTable_ = table; |
| visited_ = new Hashtable<BarrierExpression, List<BarrierExpression>>(); |
| barrierErrors_ = new ArrayList<ErrorMessage>(); |
| } |
| |
| public List<ErrorMessage> getErrors() { |
| return barrierErrors_; |
| } |
| |
| /** |
| * Determine matching of MPI barriers. |
| * |
| * @param reportErrors |
| * if true, produces a popup warning of barrier errors when |
| * found. <br> |
| * if false, no popup occurs. Useful for running under JUnit |
| * test, with no user interaction. Note that reportErrors is also |
| * used to make sure only a single error is reported - the popup |
| * warning, if shown, is only shown once per analysis. |
| * @since 4.0 |
| */ |
| public void run(boolean reportErrors) { |
| for (ICallGraphNode n = cg_.botEntry(); n != null; n = n.botNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked || !node.barrierRelated()) |
| continue; |
| // System.out.println(node.getFuncName()); |
| currentFunc_ = node; |
| cfg_ = node.getCFG(); |
| Hashtable<String, BarrierExpression> barrierExpr = node.getBarrierExpr(); |
| for (Enumeration<String> e = barrierExpr.keys(); e.hasMoreElements();) { |
| currentComm_ = (String) e.nextElement(); |
| BarrierExpression be = barrierExpr.get(currentComm_); |
| error = false; |
| fixedLength(be); |
| if (error) { |
| // Don't report an error dialog for *each* barrier matching |
| // error found |
| // Only the first one, if at all |
| if (reportErrors) { |
| reportErrors = false; // don't report any more |
| String errorMsg = Messages.MPIBarrierMatching_foundBarrierSyncError; |
| MessageDialog.openInformation(ShowMatchSet |
| .getStandardDisplay().getActiveShell(), |
| Messages.MPIBarrierMatching_mpiBarrierAnalysis, errorMsg); |
| } |
| |
| } |
| findMatches(be); |
| } |
| } |
| // symmMatches(); |
| if (traceOn) |
| printMatches(); |
| if (traceOn) |
| System.out.println("mv = " + mv + ", sv = " + sv); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| protected void fixedLength(BarrierExpression BE) { |
| // System.out.println(BE.prettyPrinter()); |
| BarrierExpressionOP OP = BE.getOP(); |
| if (OP == null) { |
| if (BE.isBot()) { |
| BE.setLength(0); |
| } |
| else if (BE.isBarrier()) { |
| BE.setLength(1); |
| } |
| else { // function call |
| String funcName = BE.getFuncName(); |
| MPICallGraphNode fnode = (MPICallGraphNode) cg_.getNode(currentFunc_.getFileName(), funcName); |
| if (fnode != null && fnode.barrierRelated()) { |
| if (fnode.isRecursive()) |
| BE.setLength(BarrierExpression.TOP); |
| else { |
| BarrierExpression fBE = fnode.getBarrierExpr().get(currentComm_); |
| BE.setLength(fBE.getLength()); |
| } |
| } else { |
| BE.setLength(0); |
| } |
| } |
| } |
| else if (OP.getOperator() == BarrierExpressionOP.op_concat) { |
| BarrierExpression oprd1 = BE.getOP1(); |
| BarrierExpression oprd2 = BE.getOP2(); |
| fixedLength(oprd1); |
| fixedLength(oprd2); |
| int length1 = oprd1.getLength(); |
| int length2 = oprd2.getLength(); |
| |
| if (length1 == BarrierExpression.TOP || length2 == BarrierExpression.TOP) { |
| BE.setLength(BarrierExpression.TOP); |
| } else { |
| BE.setLength(length1 + length2); |
| } |
| } |
| else if (OP.getOperator() == BarrierExpressionOP.op_branch) { |
| /* need special treatment for conditional expression */ |
| BarrierExpression oprd1 = BE.getOP1(); |
| BarrierExpression oprd2 = BE.getOP2(); |
| fixedLength(oprd1); |
| fixedLength(oprd2); |
| int length1 = oprd1.getLength(); |
| int length2 = oprd2.getLength(); |
| MPIBlock cond = (MPIBlock) cfg_.getBlock(OP.getCondition(), OP.getStatement()); |
| if (cond.getMV()) |
| mv++; |
| else |
| sv++; |
| if (length1 == BarrierExpression.TOP || length2 == BarrierExpression.TOP) { |
| BE.setLength(BarrierExpression.TOP); |
| if (cond.getMV()) { |
| BE.setErrorFlag(true); |
| if (!(oprd1.getErrorFlag() || oprd2.getErrorFlag())) { |
| // We only report errors in the lowest level |
| reportWarning(BE); |
| } |
| } |
| } else if (length1 == length2) { |
| BE.setLength(length1); |
| } else { // length1 != TOP && length2 != TOP && length1 != length2 |
| BE.setLength(BarrierExpression.TOP); |
| if (cond.getMV()) { |
| BE.setErrorFlag(true); |
| if (!(oprd1.getErrorFlag() || oprd2.getErrorFlag())) { |
| reportWarning(BE); |
| } |
| |
| } |
| } |
| } |
| else { // BarrierExpressionOP.op_repeat |
| BarrierExpression oprd = BE.getOP1(); |
| fixedLength(oprd); |
| MPIBlock cond = (MPIBlock) cfg_.getBlock(OP.getCondition(), OP.getStatement()); |
| if (cond.getMV()) |
| mv++; |
| else |
| sv++; |
| if (oprd.getLength() == 0) { |
| BE.setLength(0); |
| } else { |
| BE.setLength(BarrierExpression.TOP); |
| if (cond.getMV()) { |
| BE.setErrorFlag(true); |
| if (!oprd.getErrorFlag()) { |
| reportWarning(BE); |
| } |
| |
| } |
| } |
| } |
| } |
| |
| protected void reportWarning(BarrierExpression BE) { |
| error = true; |
| |
| IASTStatement stmt = BE.getOP().getStatement(); |
| if (traceOn) |
| System.out.println("Barrier mismatching found in " + stmt); //$NON-NLS-1$ |
| IASTExpression cond = null; |
| |
| if (stmt instanceof IASTIfStatement) |
| cond = ((IASTIfStatement) stmt).getConditionExpression(); |
| else if (stmt instanceof IASTDoStatement) |
| cond = ((IASTDoStatement) stmt).getCondition(); |
| else if (stmt instanceof IASTForStatement) |
| cond = ((IASTForStatement) stmt).getConditionExpression(); |
| else if (stmt instanceof IASTWhileStatement) |
| cond = ((IASTWhileStatement) stmt).getCondition(); |
| else if (stmt instanceof IASTSwitchStatement) |
| cond = ((IASTSwitchStatement) stmt).getControllerExpression(); |
| else { |
| System.out.println("Barrier Expression doesn't have valid condition"); //$NON-NLS-1$ |
| return; |
| } |
| |
| int line = -1; |
| IASTNodeLocation[] locations = cond.getNodeLocations(); |
| if (locations.length == 1) { |
| IASTFileLocation astFileLocation = null; |
| if (locations[0] instanceof IASTFileLocation) { |
| astFileLocation = (IASTFileLocation) locations[0]; |
| line = astFileLocation.getStartingLineNumber(); |
| } |
| } |
| |
| try { |
| // Don't want it to be a problem marker: then it's harder to delete |
| // (don't |
| // want to delete the other problem markers) |
| // IMarker m = |
| // currentFunc_.getResource().createMarker(IMarker.PROBLEM); |
| IMarker m = currentFunc_.getResource().createMarker(IDs.errorMarkerID); |
| // IMarker m = |
| // currentFunc_.getResource().createMarker(IDs.errorMarkerID); |
| m.setAttribute(IMarker.LINE_NUMBER, line); |
| m.setAttribute(IMarker.MESSAGE, Messages.MPIBarrierMatching_barrierSyncError); |
| m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); |
| m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); |
| } catch (CoreException e) { |
| System.out.println("RM: exception creating markers."); //$NON-NLS-1$ |
| e.printStackTrace(); |
| } |
| |
| ErrorMessage err = new ErrorMessage(cond, stmt, currentFunc_.getFuncName(), |
| currentFunc_.getFileName(), currentFunc_.getResource()); |
| counterExample(BE, err); |
| barrierErrors_.add(err); |
| } |
| |
| private boolean changed = false; |
| |
| protected void counterExample(BarrierExpression BE, ErrorMessage err) { |
| BarrierExpressionOP op = BE.getOP(); |
| if (op.getOperator() == BarrierExpressionOP.op_branch) { |
| List<PathNode> path1 = new ArrayList<PathNode>(); |
| List<PathNode> path2 = new ArrayList<PathNode>(); |
| boolean first = true; |
| while (true) { |
| changed = false; |
| traverseBarrierExpr(path1, BE.getOP1(), cfg_); |
| traverseBarrierExpr(path2, BE.getOP2(), cfg_); |
| if (differentLength(path1, path2)) |
| break; |
| if (!changed && !first) { |
| System.out.println("We cannot find the counter example!"); //$NON-NLS-1$ |
| } |
| if (first) |
| first = true; |
| path1 = new ArrayList<PathNode>(); |
| path2 = new ArrayList<PathNode>(); |
| } |
| err.setPath1(path1); |
| err.setPath2(path2); |
| |
| if (traceOn) |
| System.out.println("Path 1: "); //$NON-NLS-1$ |
| for (Iterator<PathNode> i = path1.iterator(); i.hasNext();) { |
| PathNode pn = i.next(); |
| pn.print(); |
| if (traceOn) |
| System.out.print(", "); //$NON-NLS-1$ |
| } |
| if (traceOn) |
| System.out.println(" "); //$NON-NLS-1$ |
| if (traceOn) |
| System.out.println("Path 2: "); //$NON-NLS-1$ |
| for (Iterator<PathNode> i = path2.iterator(); i.hasNext();) { |
| PathNode pn = i.next(); |
| pn.print(); |
| if (traceOn) |
| System.out.print(", "); //$NON-NLS-1$ |
| } |
| if (traceOn) |
| System.out.println(" "); //$NON-NLS-1$ |
| } |
| else if (op.getOperator() == BarrierExpressionOP.op_repeat) { |
| List<PathNode> path1 = new ArrayList<PathNode>(); |
| traverseBarrierExpr(path1, BE.getOP1(), cfg_); |
| for (Iterator<PathNode> i = path1.iterator(); i.hasNext();) { |
| PathNode pn = i.next(); |
| pn.setRepeat(true); |
| } |
| err.setPath1(path1); |
| |
| if (traceOn) |
| System.out.println("Path: "); //$NON-NLS-1$ |
| for (Iterator<PathNode> i = path1.iterator(); i.hasNext();) { |
| PathNode pn = i.next(); |
| pn.print(); |
| if (traceOn) |
| System.out.print(", "); //$NON-NLS-1$ |
| } |
| if (traceOn) |
| System.out.println(" "); //$NON-NLS-1$ |
| } |
| } |
| |
| protected void traverseBarrierExpr(List<PathNode> path, BarrierExpression BE, |
| IControlFlowGraph cfg) { |
| // System.out.println(BE.prettyPrinter()); |
| BarrierExpressionOP op = BE.getOP(); |
| if (op == null) { |
| if (BE.isBot()) { |
| return; |
| } |
| else if (BE.isBarrier()) { |
| BarrierInfo barrier = barrierTable_.searchBarrierbyID(BE.getBarrierID()); |
| PathNode pn = new PathNode(barrier, false); |
| path.add(pn); |
| } |
| else { // function call |
| String funcName = BE.getFuncName(); |
| MPICallGraphNode fnode = (MPICallGraphNode) cg_.getNode(currentFunc_.getFileName(), funcName); |
| if (fnode != null && fnode.barrierRelated()) { |
| BarrierExpression fBE = (BarrierExpression) fnode.getBarrierExpr().get(currentComm_); |
| traverseBarrierExpr(path, fBE, fnode.getCFG()); |
| } else { |
| return; |
| } |
| } |
| } |
| else if (op.getOperator() == BarrierExpressionOP.op_branch) { |
| MPIBlock cond = (MPIBlock) cfg.getBlock(op.getCondition(), op.getStatement()); |
| if (cond.getMV()) { |
| /* |
| * Concurrent branch. Both branches should have same lengths, |
| * thus it doesn't matter which branch to choose. By default we |
| * choose the left branch. |
| */ |
| traverseBarrierExpr(path, BE.getOP1(), cfg); |
| } else if (BE.getLength() != BarrierExpression.TOP) { |
| /* Both branches have same length that are not \TOP */ |
| traverseBarrierExpr(path, BE.getOP1(), cfg); |
| } else if (changed) { |
| /* |
| * Some change has been made somewhere else. So keep the |
| * previous choice at this point |
| */ |
| if (BE.getOP2().ceVisited) |
| traverseBarrierExpr(path, BE.getOP2(), cfg); |
| else |
| traverseBarrierExpr(path, BE.getOP1(), cfg); |
| } else { |
| /* Nothing changed till now */ |
| if (BE.getOP2().ceVisited) { |
| /* We cannot make any change. Keep the previous choice */ |
| traverseBarrierExpr(path, BE.getOP2(), cfg); |
| } else if (BE.getOP1().ceVisited) { |
| /* Make change here */ |
| traverseBarrierExpr(path, BE.getOP2(), cfg); |
| changed = true; |
| } else { |
| /* This BE is visited the first time */ |
| traverseBarrierExpr(path, BE.getOP1(), cfg); |
| } |
| } |
| } |
| else if (op.getOperator() == BarrierExpressionOP.op_concat) { |
| traverseBarrierExpr(path, BE.getOP1(), cfg); |
| traverseBarrierExpr(path, BE.getOP2(), cfg); |
| } |
| else if (op.getOperator() == BarrierExpressionOP.op_repeat) { |
| traverseBarrierExpr(path, BE.getOP1(), cfg); |
| for (Iterator<PathNode> i = path.iterator(); i.hasNext();) { |
| PathNode pn = i.next(); |
| pn.setRepeat(true); |
| } |
| } |
| BE.ceVisited = true; |
| } |
| |
| protected boolean differentLength(List<PathNode> path1, List<PathNode> path2) { |
| if (path1.size() != path2.size()) |
| return true; |
| for (int i = 0; i < path1.size(); i++) { |
| if (path1.get(i).isRepeat() || path2.get(i).isRepeat()) |
| return true; |
| } |
| return false; |
| } |
| |
| public class PathNode { |
| private BarrierInfo barrier_; |
| private boolean repeat; |
| |
| public PathNode(BarrierInfo barrier, boolean repeat) { |
| this.barrier_ = barrier; |
| this.repeat = repeat; |
| } |
| |
| public PathNode(BarrierInfo barrier) { |
| this.barrier_ = barrier; |
| repeat = false; |
| } |
| |
| public void setRepeat(boolean val) { |
| repeat = val; |
| } |
| |
| public boolean isRepeat() { |
| return repeat; |
| } |
| |
| public BarrierInfo getBarrier() { |
| return barrier_; |
| } |
| |
| public void print() { |
| if (traceOn) |
| System.out.print(barrier_.getID()); |
| if (repeat) |
| if (traceOn) |
| System.out.print("(*)"); //$NON-NLS-1$ |
| } |
| } |
| |
| public class ErrorMessage { |
| private IASTExpression position_; |
| private IASTStatement errStmt_; |
| private String funcName_; |
| private String fileName_; |
| private SourceInfo sourceInfo_; |
| private SourceInfo path1SourceInfo_; |
| private SourceInfo path2SourceInfo_; |
| private IResource resource_; |
| private List<PathNode> path1_ = null; |
| private List<PathNode> path2_ = null; |
| private int length1 = 0; |
| private int length2 = 0; |
| |
| public ErrorMessage(IASTExpression pos, IASTStatement stmt, String funcName, |
| String fileName, IResource res) { |
| position_ = pos; |
| errStmt_ = stmt; |
| funcName_ = funcName; |
| fileName_ = fileName; |
| resource_ = res; |
| sourceInfo_ = getSourceInfo(position_); |
| if (errStmt_ instanceof IASTIfStatement) { |
| IASTIfStatement ifS = (IASTIfStatement) errStmt_; |
| path1SourceInfo_ = getSourceInfo(ifS.getThenClause()); |
| path2SourceInfo_ = getSourceInfo(ifS.getElseClause()); |
| } else if (errStmt_ instanceof IASTDoStatement) { |
| IASTDoStatement doS = (IASTDoStatement) errStmt_; |
| path1SourceInfo_ = getSourceInfo(doS.getBody()); |
| path2SourceInfo_ = null; |
| } else if (errStmt_ instanceof IASTForStatement) { |
| IASTForStatement forS = (IASTForStatement) errStmt_; |
| path1SourceInfo_ = getSourceInfo(forS.getBody()); |
| path2SourceInfo_ = null; |
| } else if (errStmt_ instanceof IASTWhileStatement) { |
| IASTWhileStatement whileS = (IASTWhileStatement) errStmt_; |
| path1SourceInfo_ = getSourceInfo(whileS.getBody()); |
| path2SourceInfo_ = null; |
| } else if (errStmt_ instanceof IASTSwitchStatement) { |
| IASTSwitchStatement switchS = (IASTSwitchStatement) errStmt_; |
| path1SourceInfo_ = getSourceInfo(switchS.getBody()); |
| path2SourceInfo_ = path1SourceInfo_; |
| } |
| } |
| |
| SourceInfo getSourceInfo(IASTNode node) { |
| SourceInfo sourceInfo = new SourceInfo(); |
| if (node == null) |
| return sourceInfo; |
| IASTNodeLocation[] locations = node.getNodeLocations(); |
| if (locations.length == 1) { |
| IASTFileLocation astFileLocation = null; |
| if (locations[0] instanceof IASTFileLocation) { |
| astFileLocation = (IASTFileLocation) locations[0]; |
| sourceInfo.setStartingLine(astFileLocation.getStartingLineNumber()); |
| sourceInfo.setStart(astFileLocation.getNodeOffset()); |
| sourceInfo.setEnd(astFileLocation.getNodeOffset() + astFileLocation.getNodeLength()); |
| sourceInfo.setConstructType(Artifact.NONE); |
| } |
| } |
| else { |
| // System.out.println("MPIBarrierMatching.getSourceInfo().. ! More than one IASTNodeLocation !"); |
| // CASTCompoundStatement causes this. Probably ok? assuming it |
| // descends into the child nodes |
| if (traceOn) { |
| if (node instanceof CASTCompoundStatement) { |
| CASTCompoundStatement cstmt = (CASTCompoundStatement) node; |
| System.out.println("Compound stmt: " + cstmt.getRawSignature()); //$NON-NLS-1$ |
| IASTNodeLocation[] locs = cstmt.getNodeLocations(); |
| for (int i = 0; i < locs.length; i++) { |
| IASTNodeLocation loc = locs[i]; |
| System.out.println(" subnode: " + loc.toString()); //$NON-NLS-1$ |
| } |
| } |
| |
| } |
| } |
| return sourceInfo; |
| } |
| |
| public void setPath1(List<PathNode> path) { |
| path1_ = path; |
| int count = 0; |
| for (Iterator<PathNode> i = path.iterator(); i.hasNext();) { |
| PathNode pn = i.next(); |
| if (pn.isRepeat()) { |
| length1 = -1; |
| return; |
| } else { |
| count++; |
| } |
| } |
| length1 = count; |
| } |
| |
| public void setPath2(List<PathNode> path) { |
| path2_ = path; |
| int count = 0; |
| for (Iterator<PathNode> i = path.iterator(); i.hasNext();) { |
| PathNode pn = i.next(); |
| if (pn.isRepeat()) { |
| length2 = -1; |
| return; |
| } else { |
| count++; |
| } |
| } |
| length2 = count; |
| } |
| |
| public IASTExpression getPosition() { |
| return position_; |
| } |
| |
| public String getFuncName() { |
| return funcName_; |
| } |
| |
| public String getFileName() { |
| return fileName_; |
| } |
| |
| public SourceInfo getSourceInfo() { |
| return sourceInfo_; |
| } |
| |
| public SourceInfo getPath1SourceInfo() { |
| return path1SourceInfo_; |
| } |
| |
| public SourceInfo getPath2SourceInfo() { |
| return path2SourceInfo_; |
| } |
| |
| public IResource getResource() { |
| return resource_; |
| } |
| |
| public List<PathNode> getPath1() { |
| return path1_; |
| } |
| |
| public List<PathNode> getPath2() { |
| return path2_; |
| } |
| |
| public int getLength1() { |
| return length1; |
| } |
| |
| public int getLength2() { |
| return length2; |
| } |
| } |
| |
| protected void findMatches(BarrierExpression BE) { |
| if (traceOn) |
| System.out.println(BE.prettyPrinter()); |
| BarrierExpressionOP OP = BE.getOP(); |
| if (BE.visited) |
| return; |
| BE.visited = true; |
| if (OP == null) { |
| if (BE.isFunc()) { |
| String funcName = BE.getFuncName(); |
| MPICallGraphNode fnode = (MPICallGraphNode) cg_.getNode(currentFunc_.getFileName(), funcName); |
| if (fnode != null && fnode.barrierRelated()) { |
| BarrierExpression fBE = (BarrierExpression) fnode.getBarrierExpr().get(currentComm_); |
| findMatches(fBE); |
| } |
| } else { |
| lstack_ = new Stack<BarrierExpression>(); |
| sstack_ = new Stack<BarrierExpression>(); |
| workList_ = new LinkedList<Work>(); |
| match(BE, BE, down); |
| while (!workList_.isEmpty()) { |
| Work w = workList_.remove(); |
| match(w.BE1_, w.BE2_, w.direction); |
| } |
| } |
| } |
| else if (OP.getOperator() == BarrierExpressionOP.op_concat) { |
| BarrierExpression oprd1 = BE.getOP1(); |
| BarrierExpression oprd2 = BE.getOP2(); |
| findMatches(oprd1); |
| findMatches(oprd2); |
| } |
| else if (OP.getOperator() == BarrierExpressionOP.op_branch) { |
| BarrierExpression oprd1 = BE.getOP1(); |
| BarrierExpression oprd2 = BE.getOP2(); |
| MPIBlock cond = (MPIBlock) cfg_.getBlock(OP.getCondition(), OP.getStatement()); |
| if (cond.getMV()) { // concurrent branch |
| if (!BE.getErrorFlag()) { |
| lstack_ = new Stack<BarrierExpression>(); |
| sstack_ = new Stack<BarrierExpression>(); |
| workList_ = new LinkedList<Work>(); |
| match(oprd1, oprd2, down); |
| while (!workList_.isEmpty()) { |
| Work w = workList_.remove(); |
| match(w.BE1_, w.BE2_, w.direction); |
| } |
| } |
| } |
| if (!BE.getErrorFlag()) { |
| findMatches(oprd1); |
| findMatches(oprd2); |
| } |
| } |
| else { // BarrierExpressionOP.op_repeat |
| if (!BE.getErrorFlag()) { |
| BarrierExpression oprd = BE.getOP1(); |
| findMatches(oprd); |
| } |
| } |
| } |
| |
| protected final int down = 0; |
| protected final int up = 1; |
| protected Stack<BarrierExpression> lstack_; |
| protected Stack<BarrierExpression> sstack_; |
| protected LinkedList<Work> workList_; |
| |
| class Work { |
| BarrierExpression BE1_; |
| BarrierExpression BE2_; |
| int direction; |
| |
| Work(BarrierExpression be1, BarrierExpression be2, int direction) { |
| BE1_ = be1; |
| BE2_ = be2; |
| this.direction = direction; |
| } |
| } |
| |
| protected void match(BarrierExpression BE1, BarrierExpression BE2, int dir) { |
| BarrierExpression T1 = BE1; |
| BarrierExpression T2 = BE2; |
| int direction = dir; |
| while (true) { |
| if (traceOn) |
| System.out.println("match: " + T1.prettyPrinter()); //$NON-NLS-1$ |
| if (traceOn) |
| System.out.println(" " + T2.prettyPrinter()); //$NON-NLS-1$ |
| if (direction == down) { |
| if (traceOn) |
| System.out.println(" down");} //$NON-NLS-1$ |
| else { |
| if (traceOn) |
| System.out.println(" up");} //$NON-NLS-1$ |
| |
| if (direction == down && !pairVisited(T1, T2)) |
| addVisitedPair(T1, T2); |
| |
| BarrierExpressionOP OP1 = T1.getOP(); |
| BarrierExpressionOP OP2 = T2.getOP(); |
| |
| if (direction == up && T1 == BE1 && T2 == BE2) |
| break; |
| else if (direction == down && OP1 == null && OP2 == null && |
| T1.isBot() && T2.isBot()) |
| direction = up; |
| else if (direction == down && OP1 == null && OP2 == null && |
| T1.isBarrier() && T2.isBarrier()) { |
| addMatchedPair(T1, T2); // BRT 5 and 5 ??? |
| addMatchedPair(T1, T1); |
| addMatchedPair(T2, T2); |
| direction = up; |
| } else if (direction == down && OP1 == null && T1.isFunc()) { // rule |
| // 7 |
| String funcName = T1.getFuncName(); |
| MPICallGraphNode fnode = (MPICallGraphNode) cg_.getNode(currentFunc_.getFileName(), funcName); |
| if (fnode == null || !fnode.barrierRelated()) { |
| System.out.println("Error in call graph"); //$NON-NLS-1$ |
| } |
| BarrierExpression fBE = (BarrierExpression) fnode.getBarrierExpr().get(currentComm_); |
| lstack_.push(T1); |
| T1 = fBE; |
| } else if (direction == down && OP2 == null && T2.isFunc()) { // rule |
| // 7 |
| String funcName = T2.getFuncName(); |
| MPICallGraphNode fnode = (MPICallGraphNode) cg_.getNode(currentFunc_.getFileName(), funcName); |
| if (fnode == null || !fnode.barrierRelated()) { |
| System.out.println("Error in call graph"); //$NON-NLS-1$ |
| } |
| BarrierExpression fBE = (BarrierExpression) fnode.getBarrierExpr().get(currentComm_); |
| sstack_.push(T2); |
| T2 = fBE; |
| } else if (direction == down && OP1 != null && |
| OP1.getOperator() == BarrierExpressionOP.op_concat) { // rule |
| // 2 |
| T1 = T1.getOP1(); |
| } else if (direction == down && OP2 != null && |
| OP2.getOperator() == BarrierExpressionOP.op_concat) { // rule |
| // 2 |
| T2 = T2.getOP1(); |
| } else if (direction == up && T1.getParent() == null) { // rule 8 |
| T1 = lstack_.pop(); |
| } else if (direction == up && T2.getParent() == null) { // rule 8 |
| T2 = sstack_.pop(); |
| } else if (direction == up && |
| T1.getParent().getOP().getOperator() == BarrierExpressionOP.op_concat |
| && T1 == T1.getParent().getOP2()) { // rule 3 |
| T1 = T1.getParent(); |
| direction = up; |
| } else if (direction == up && |
| T2.getParent().getOP().getOperator() == BarrierExpressionOP.op_concat |
| && T2 == T2.getParent().getOP2()) { // rule 3 |
| T2 = T2.getParent(); |
| direction = up; |
| } else if (direction == up && T1.getParent().getOP().getOperator() == BarrierExpressionOP.op_concat |
| && T1 == T1.getParent().getOP1() |
| && T2.getParent().getOP().getOperator() == BarrierExpressionOP.op_concat |
| && T2 == T2.getParent().getOP1()) { // rule 4 |
| T1 = T1.getParent().getOP2(); |
| T2 = T2.getParent().getOP2(); |
| direction = down; |
| } else if (direction == down && OP1 != null && |
| OP1.getOperator() == BarrierExpressionOP.op_branch) { // rule |
| // 5 |
| workList_.add(new Work(T1.getOP2(), T2, down)); |
| T1 = T1.getOP1(); |
| } else if (direction == down && OP2 != null && |
| OP2.getOperator() == BarrierExpressionOP.op_branch) { // rule |
| // 5 |
| workList_.add(new Work(T1, T2.getOP2(), down)); |
| T2 = T2.getOP1(); |
| } else if (direction == up && |
| T1.getParent().getOP().getOperator() == BarrierExpressionOP.op_branch) { |
| // rule 6 |
| T1 = T1.getParent(); |
| } else if (direction == up && |
| T2.getParent().getOP().getOperator() == BarrierExpressionOP.op_branch) { |
| // rule 6 |
| T2 = T2.getParent(); |
| } else { |
| System.out.println("cannot find rules for " + T1.prettyPrinter() //$NON-NLS-1$ |
| + " and " + T2.prettyPrinter() + " and direction = " + direction); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| |
| protected void addVisitedPair(BarrierExpression b1, BarrierExpression b2) { |
| List<BarrierExpression> visitedPair = visited_.get(b1); |
| if (visitedPair == null) { |
| visitedPair = new ArrayList<BarrierExpression>(); |
| visitedPair.add(b2); |
| visited_.put(b1, visitedPair); |
| } else { |
| if (!visitedPair.contains(b2)) |
| visitedPair.add(b2); |
| } |
| |
| visitedPair = visited_.get(b2); |
| if (visitedPair == null) { |
| visitedPair = new ArrayList<BarrierExpression>(); |
| visitedPair.add(b1); |
| visited_.put(b2, visitedPair); |
| } else { |
| if (!visitedPair.contains(b1)) |
| visitedPair.add(b1); |
| } |
| |
| } |
| |
| protected boolean pairVisited(BarrierExpression b1, BarrierExpression b2) { |
| List<BarrierExpression> pair = visited_.get(b1); |
| if (pair == null || !pair.contains(b2)) |
| return false; |
| else |
| return true; |
| } |
| |
| protected void addMatchedPair(BarrierExpression b1, BarrierExpression b2) { |
| BarrierInfo bar1 = barrierTable_.searchBarrierbyID(b1.getBarrierID()); |
| BarrierInfo bar2 = barrierTable_.searchBarrierbyID(b2.getBarrierID()); |
| List<BarrierInfo> set1 = bar1.getMatchingSet(); |
| List<BarrierInfo> set2 = bar2.getMatchingSet(); |
| if (!set1.contains(bar2)) |
| set1.add(bar2); // adds to matchingSet_ |
| if (!set2.contains(bar1)) |
| set2.add(bar1); |
| } |
| |
| protected void symmMatches() { |
| for (Enumeration<List<BarrierInfo>> e = barrierTable_.getTable().elements(); e.hasMoreElements();) { |
| List<BarrierInfo> list = e.nextElement(); |
| for (Iterator<BarrierInfo> i = list.iterator(); i.hasNext();) { |
| BarrierInfo bar = i.next(); |
| if (traceOn) |
| System.out.println("bar = " + bar.getID()); //$NON-NLS-1$ |
| for (Iterator<BarrierInfo> ii = bar.getMatchingSet().iterator(); ii.hasNext();) { |
| BarrierInfo matchedBar = ii.next(); |
| if (traceOn) |
| System.out.println("matchedBar = " + matchedBar.getID()); //$NON-NLS-1$ |
| if (!matchedBar.getMatchingSet().contains(bar)) { |
| if (traceOn) |
| System.out.println("bar = " + bar.getID() + ", matchedBar = " + matchedBar.getID()); //$NON-NLS-1$ //$NON-NLS-2$ |
| matchedBar.getMatchingSet().add(bar); |
| } |
| } |
| } |
| } |
| } |
| |
| protected void printMatches() { |
| for (Enumeration<List<BarrierInfo>> e = barrierTable_.getTable().elements(); e.hasMoreElements();) { |
| List<BarrierInfo> list = e.nextElement(); |
| for (Iterator<BarrierInfo> i = list.iterator(); i.hasNext();) { |
| BarrierInfo bar = i.next(); |
| if (traceOn) |
| System.out.print("Barrier " + bar.getID() + " matches to : "); //$NON-NLS-1$ //$NON-NLS-2$ |
| for (Iterator<BarrierInfo> ii = bar.getMatchingSet().iterator(); ii.hasNext();) { |
| BarrierInfo matchedBar = ii.next(); |
| if (traceOn) |
| System.out.print(matchedBar.getID() + ", "); //$NON-NLS-1$ |
| } |
| } |
| if (traceOn) |
| System.out.println(" "); //$NON-NLS-1$ |
| } |
| } |
| } |