| /********************************************************************** |
| * Copyright (c) 2007,2010 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.ASTVisitor; |
| import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTCastExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTConditionalExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclaration; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTDeclarator; |
| import org.eclipse.cdt.core.dom.ast.IASTDoStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTExpressionList; |
| import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTFieldReference; |
| import org.eclipse.cdt.core.dom.ast.IASTForStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; |
| import org.eclipse.cdt.core.dom.ast.IASTIdExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTIfStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTInitializer; |
| import org.eclipse.cdt.core.dom.ast.IASTInitializerClause; |
| import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTInitializerList; |
| import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTName; |
| import org.eclipse.cdt.core.dom.ast.IASTNode; |
| import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; |
| import org.eclipse.cdt.core.dom.ast.IASTProblemExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; |
| import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; |
| import org.eclipse.cdt.core.dom.ast.IASTStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; |
| import org.eclipse.cdt.core.dom.ast.IASTWhileStatement; |
| import org.eclipse.cdt.core.dom.ast.c.ICASTTypeIdInitializerExpression; |
| import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; |
| import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousExpression; |
| import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.IBlock; |
| 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; |
| |
| /** |
| * MPI Multi-Valued analysis |
| * |
| * @author zhangyua |
| * |
| */ |
| public class MPIMVAnalysis { |
| class BroadCastAnalyzer extends ASTVisitor { |
| private final IBlock block_; |
| private String var; |
| |
| public BroadCastAnalyzer(IBlock block) { |
| block_ = block; |
| var = null; |
| } |
| |
| public String getBCdata() { |
| return var; |
| } |
| |
| public void run() { |
| this.shouldVisitStatements = true; |
| this.shouldVisitExpressions = true; |
| IASTNode content = block_.getContent(); |
| if (content != null) { |
| content.accept(this); |
| } |
| } |
| |
| @Override |
| public int visit(IASTExpression expr) { |
| if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcE = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcE.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| if (signature.equals("MPI_Bcast")) { //$NON-NLS-1$ |
| IASTInitializerClause[] arguments = funcE.getArguments(); |
| if (arguments.length > 0 && arguments[0] instanceof IASTExpression) { |
| IASTExpression dataE = (IASTExpression) arguments[0]; |
| if (dataE instanceof IASTIdExpression) { |
| IASTIdExpression ID = (IASTIdExpression) dataE; |
| var = ID.getName().toString(); |
| } else if (dataE instanceof IASTUnaryExpression) { |
| IASTUnaryExpression uE = (IASTUnaryExpression) dataE; |
| if (uE.getOperator() == IASTUnaryExpression.op_amper && uE.getOperand() instanceof IASTIdExpression) { |
| IASTIdExpression ID = (IASTIdExpression) uE.getOperand(); |
| var = ID.getName().toString(); |
| } |
| } |
| } |
| } |
| return PROCESS_SKIP; |
| } |
| return PROCESS_CONTINUE; |
| } |
| |
| } |
| |
| /** |
| * Expression Multi-valued Analyzer |
| * |
| */ |
| class ExprMVAnalyzer { |
| private IASTStatement stmt_; |
| private IASTExpression expr_; |
| private final List<String> context_; |
| private final MPIBlock currentBlock_; |
| |
| private final List<String> MVvar_; |
| private final Stack<boolean[]> exprListMVContext_; |
| |
| private boolean value; |
| |
| public ExprMVAnalyzer(IASTExpression expr, List<String> context, MPIBlock block) { |
| stmt_ = null; |
| expr_ = expr; |
| context_ = context; |
| currentBlock_ = block; |
| MVvar_ = new ArrayList<String>(); |
| exprListMVContext_ = new Stack<boolean[]>(); |
| value = false; |
| } |
| |
| public ExprMVAnalyzer(IASTNode node, List<String> context, MPIBlock block) {// BRT |
| // this |
| // one |
| // is |
| // called |
| if (node instanceof IASTExpression) { |
| stmt_ = null; |
| expr_ = (IASTExpression) node; |
| } else if (node instanceof IASTStatement) { |
| stmt_ = (IASTStatement) node; |
| expr_ = null; |
| } |
| context_ = context; |
| currentBlock_ = block; |
| MVvar_ = new ArrayList<String>(); |
| exprListMVContext_ = new Stack<boolean[]>(); |
| value = false; |
| } |
| |
| public ExprMVAnalyzer(IASTStatement stmt, List<String> context, MPIBlock block) { |
| stmt_ = stmt; |
| expr_ = null; |
| context_ = context; |
| currentBlock_ = block; |
| MVvar_ = new ArrayList<String>(); |
| exprListMVContext_ = new Stack<boolean[]>(); |
| value = false; |
| } |
| |
| public List<String> getMVList() { |
| return MVvar_; |
| } |
| |
| public boolean isMV() { |
| return value; |
| } |
| |
| public void run() { |
| if (stmt_ != null) { |
| value = useDefMVMapping(stmt_); |
| } else if (expr_ != null) { |
| List<String> defset = new ArrayList<String>(); |
| value = useDefMVMapping(expr_, rhs, null, defset); |
| } |
| } |
| |
| /** |
| * Returns true if multi-valued? //BRT |
| * |
| * @param init |
| * @return |
| */ |
| // BRT make sure this gets called, but will it be with these args? |
| // / not in a tree walk; perhaps with args gleaned from fn call |
| private boolean handleInitializer(IASTInitializer init) { |
| if (init instanceof IASTInitializerExpression) { |
| IASTInitializerExpression initE = (IASTInitializerExpression) init; |
| IASTExpression expr = initE.getExpression(); |
| List<String> mvlist = new ArrayList<String>(); |
| return useDefMVMapping(expr, rhs, null, mvlist); |
| } else if (init instanceof IASTInitializerList) {// BRT |
| IASTInitializerList initList = (IASTInitializerList) init; |
| IASTInitializer[] list = initList.getInitializers(); |
| boolean listvalue = false; |
| for (int i = 0; i < list.length; i++) { |
| listvalue = listvalue | handleInitializer(list[i]); |
| } |
| return listvalue; |
| } |
| return false; |
| } |
| |
| /** |
| * @param side |
| * @param set |
| * @param v1 |
| * @param l1 |
| * @param funcE |
| * @param newParameterList |
| * @param n |
| * @param returnval |
| * @return |
| */ |
| private boolean newParameterUse(int side, List<String> set, boolean v1, List<String> l1, IASTFunctionCallExpression funcE, |
| IASTInitializerClause[] newParameterList, MPICallGraphNode n, boolean returnval) { |
| if (newParameterList != null) { |
| |
| // boolean[] newContext = new boolean[parameter2.length]; |
| boolean context; |
| for (int i = 0; i < newParameterList.length; i++) { |
| IASTInitializerClause ic = newParameterList[i]; |
| if (ic instanceof IASTExpression) { // BRT?? is it?? |
| ic.getRawSignature(); |
| IASTExpression iexpr = (IASTExpression) ic; |
| v1 = v1 | useDefMVMapping(iexpr, side, funcE, l1); |
| context = v1; |
| Util.addAll(set, l1); // BRT ????? |
| |
| // --- put this inside this loop, don't need another |
| // loop |
| if (context) { |
| String param = getFormalParamName(n, i); |
| if (param != null) { |
| List<String> mvlist = n.getMVSummary().get(param); |
| Util.addAll(MVvar_, mvlist); |
| if (mvlist.contains(n.getFuncName())) { // return |
| // MV |
| // value |
| MVvar_.remove(n.getFuncName()); |
| returnval = true; |
| } |
| } |
| } |
| // --- |
| } |
| // omit exprListMVContext_.push(newContext); |
| } |
| |
| } |
| return returnval; |
| } |
| |
| /** |
| * @param parameter |
| * @param cgNode |
| * @param returnval |
| * @return |
| */ |
| private boolean oldParameterUse(IASTExpression parameter, MPICallGraphNode cgNode, boolean returnval) { |
| if (parameter instanceof IASTExpressionList) { // >1 parameter |
| boolean[] paramContext = exprListMVContext_.pop(); |
| for (int i = 0; i < paramContext.length; i++) { |
| if (paramContext[i]) { |
| String param = getFormalParamName(cgNode, i); |
| if (param != null) { |
| List<String> mvlist = cgNode.getMVSummary().get(param); |
| Util.addAll(MVvar_, mvlist); |
| if (mvlist.contains(cgNode.getFuncName())) { // return |
| // MV |
| // value |
| MVvar_.remove(cgNode.getFuncName()); |
| returnval = true; |
| } |
| } |
| } |
| } |
| } else { // single parameter |
| String param = getFormalParamName(cgNode, 0); |
| if (param != null) { |
| List<String> mvlist = cgNode.getMVSummary().get(param); |
| Util.addAll(MVvar_, mvlist); |
| if (mvlist.contains(cgNode.getFuncName())) { // return MV |
| // value |
| MVvar_.remove(cgNode.getFuncName()); |
| returnval = true; |
| } |
| } |
| } |
| return returnval; |
| } |
| |
| /** |
| * Return true if "expr" is multi_valued. |
| * |
| * @param expr |
| * expression to determine if multi-valued |
| * @param side |
| * LHS or RHS |
| * @param func |
| * @param set |
| * contains all defined variables in "expr" through |
| * assignment |
| */ |
| private boolean useDefMVMapping(IASTExpression expr, int side, IASTFunctionCallExpression func, List<String> set) { |
| boolean v1 = false, v2 = false, v3 = false; |
| List<String> l1 = new ArrayList<String>(); |
| List<String> l2 = new ArrayList<String>(); |
| List<String> l3 = new ArrayList<String>(); |
| if (expr == null) { |
| return false; |
| } |
| if (expr instanceof IASTAmbiguousExpression) { |
| } else if (expr instanceof IASTArraySubscriptExpression) { |
| IASTArraySubscriptExpression asE = (IASTArraySubscriptExpression) expr; |
| if (side == rhs) { |
| // = a[index_expr] |
| v1 = useDefMVMapping(asE.getArrayExpression(), rhs, func, l1); |
| v2 = useDefMVMapping(asE.getSubscriptExpression(), rhs, func, l2); |
| } else { // lhs |
| // a[b[i]] = ... , a is defined, b and i are used |
| v1 = useDefMVMapping(asE.getSubscriptExpression(), rhs, func, l1); |
| v2 = useDefMVMapping(asE.getArrayExpression(), lhs, func, l2); |
| } |
| Util.addAll(set, l1); |
| Util.addAll(set, l2); |
| return v1 | v2; |
| } else if (expr instanceof IASTBinaryExpression) { |
| IASTBinaryExpression biE = (IASTBinaryExpression) expr; |
| int op = biE.getOperator(); |
| if (op == IASTBinaryExpression.op_assign) { |
| // x = y = z is right associative --> x = (y = z) |
| // So the "side" will be always rhs |
| v1 = useDefMVMapping(biE.getOperand1(), lhs, func, l1); |
| v2 = useDefMVMapping(biE.getOperand2(), rhs, func, l2); |
| if (v2) { |
| Util.addAll(MVvar_, l1); |
| } |
| Util.addAll(set, l1); |
| Util.addAll(set, l2); |
| } else if (op == IASTBinaryExpression.op_multiplyAssign || op == IASTBinaryExpression.op_divideAssign |
| || op == IASTBinaryExpression.op_moduloAssign || op == IASTBinaryExpression.op_plusAssign |
| || op == IASTBinaryExpression.op_minusAssign || op == IASTBinaryExpression.op_shiftLeftAssign |
| || op == IASTBinaryExpression.op_shiftRightAssign || op == IASTBinaryExpression.op_binaryAndAssign |
| || op == IASTBinaryExpression.op_binaryXorAssign || op == IASTBinaryExpression.op_binaryOrAssign) { |
| v1 = useDefMVMapping(biE.getOperand1(), rhs, func, l1); |
| v2 = useDefMVMapping(biE.getOperand2(), rhs, func, l2); |
| v3 = useDefMVMapping(biE.getOperand1(), lhs, func, l3); |
| if (v1 | v2) { |
| Util.addAll(MVvar_, l3); |
| } |
| Util.addAll(set, l1); |
| Util.addAll(set, l2); |
| Util.addAll(set, l3); |
| } else { |
| v1 = useDefMVMapping(biE.getOperand1(), rhs, func, l1);// BRT |
| // results |
| // are |
| // diff |
| // from |
| // 3.0! |
| v2 = useDefMVMapping(biE.getOperand2(), rhs, func, l2); |
| Util.addAll(set, l1); |
| Util.addAll(set, l2); |
| } |
| return v1 | v2 | v3; |
| } else if (expr instanceof IASTCastExpression) { |
| IASTCastExpression castE = (IASTCastExpression) expr; |
| v1 = useDefMVMapping(castE.getOperand(), side, func, l1); |
| Util.addAll(set, l1); |
| return v1; |
| } else if (expr instanceof IASTConditionalExpression) { |
| IASTConditionalExpression condE = (IASTConditionalExpression) expr; |
| if (side == rhs) { |
| v1 = useDefMVMapping(condE.getLogicalConditionExpression(), rhs, func, l1); |
| v2 = useDefMVMapping(condE.getPositiveResultExpression(), rhs, func, l2); |
| v3 = useDefMVMapping(condE.getNegativeResultExpression(), rhs, func, l3); |
| } else { |
| // eg. (x > y ? x : y) = 1 |
| v1 = useDefMVMapping(condE.getLogicalConditionExpression(), rhs, func, l1); |
| v2 = useDefMVMapping(condE.getPositiveResultExpression(), lhs, func, l2); |
| v3 = useDefMVMapping(condE.getNegativeResultExpression(), lhs, func, l3); |
| } |
| Util.addAll(set, l1); |
| Util.addAll(set, l2); |
| Util.addAll(set, l3); |
| return v1 | v2 | v3; |
| } else if (expr instanceof IASTExpressionList) {// BRT |
| // IASTExpressionList |
| // no longer in AST; |
| // see below |
| IASTExpressionList exprList = (IASTExpressionList) expr;// But |
| // this |
| // *DOES* |
| // get |
| // called. |
| // 3-deep |
| // recursive |
| // call |
| // of |
| // useDevMVMapping |
| IASTExpression[] exprs = exprList.getExpressions(); |
| boolean[] newContext_ = new boolean[exprs.length]; |
| for (int i = 0; i < exprs.length; i++) { |
| v1 = v1 | useDefMVMapping(exprs[i], side, func, l1); |
| newContext_[i] = v1; |
| Util.addAll(set, l1); |
| } |
| if (func != null) { |
| exprListMVContext_.push(newContext_);// BRT note this is NOT |
| // a field! local |
| // var only |
| } |
| return v1; |
| } else if (expr instanceof IASTFieldReference) { |
| IASTFieldReference frE = (IASTFieldReference) expr; |
| v1 = useDefMVMapping(frE.getFieldOwner(), side, func, l1); |
| Util.addAll(set, l1); |
| return v1; |
| } else if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcE = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcE.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| IASTInitializerClause[] arguments = funcE.getArguments(); |
| MPICallGraphNode cgNode = (MPICallGraphNode) cg_.getNode(currentNode_.getFileName(), signature); |
| if (cgNode != null) { // BRT always null on tiny.c. ?? |
| /* |
| * 1. Determine whether each parameter is MV or SV 2. Refer |
| * to the MVsummary, find the set of MV variables according |
| * to the parameter MV context, and find out whether the |
| * return value is MV or SV |
| */ |
| boolean returnval = false; |
| if (arguments.length > 0 && arguments[0] instanceof IASTExpression) { |
| IASTExpression parameter = (IASTExpression) arguments[0]; |
| v1 = useDefMVMapping(parameter, side, funcE, l1); |
| // BRT note with CDT 7.0 the IASTExpressionList is not |
| // encountered in the AST |
| // See bug |
| // https://bugs.eclipse.org/bugs/show_bug.cgi?id=306064 |
| // But since we get it from a method call |
| // IASTFunctionCallExpression.getParameterExpression() |
| // this probably still |
| // works ok here. |
| returnval = oldParameterUse(parameter, cgNode, returnval); |
| |
| // == end context old way |
| |
| // === new way |
| // returnval = newParameterUse(side, set, v1, l1, funcE, |
| // newParameterList, cgNode, returnval); |
| // === end new way |
| } |
| for (Iterator<String> i = cgNode.getGlobalUse().iterator(); i.hasNext();) { |
| String guse = i.next(); |
| if (context_.contains(guse)) { |
| List<String> mvlist = cgNode.getMVSummary().get(guse); |
| Util.addAll(MVvar_, mvlist); |
| if (mvlist.contains(cgNode.getFuncName())) { // return |
| // MV |
| // value |
| MVvar_.remove(cgNode.getFuncName()); |
| returnval = true; |
| } |
| } |
| } |
| if (cgNode.getMVSummary().size() == 1) {// no parameter, no |
| // global use |
| List<String> mvlist = cgNode.getMVSummary().get(cgNode.getFuncName()); |
| if (mvlist.size() == 1 && mvlist.contains(cgNode.getFuncName())) { |
| returnval = true; |
| } else { |
| returnval = false; |
| } |
| } |
| return returnval; |
| }// end if cgNode!=null |
| else { |
| if (arguments.length > 0 && arguments[0] instanceof IASTExpression) { |
| IASTExpression parameter = (IASTExpression) arguments[0]; |
| v1 = useDefMVMapping(parameter, side, funcE, l1); |
| if (parameter instanceof IASTExpressionList) { |
| exprListMVContext_.pop(); |
| } |
| Util.addAll(set, l1); |
| return v1; |
| } else { |
| return false; |
| } |
| } |
| } else if (expr instanceof IASTIdExpression) { |
| IASTIdExpression id = (IASTIdExpression) expr; |
| IASTName name = id.getName(); |
| String var = name.toString(); |
| if (var.startsWith("MPI_")) { |
| return false; //$NON-NLS-1$ |
| } |
| if (side == rhs) { |
| if (func != null) { // function parameter |
| IASTExpression funcname = func.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| ICallGraphNode n = cg_.getNode(currentNode_.getFileName(), signature); |
| if (n == null) { // library function call |
| if (currentBlock_.getDef().contains(var)) { |
| if (!set.contains(var)) { |
| set.add(var); |
| } |
| if (context_.contains(var) && !MVvar_.contains(var)) { |
| MVvar_.add(var); |
| } |
| } |
| } |
| } |
| if (context_.contains(var)) { |
| return true; |
| } |
| } else { // lhs |
| if (!set.contains(var)) { |
| set.add(var); |
| } |
| return false; |
| } |
| } else if (expr instanceof IASTLiteralExpression) { |
| } else if (expr instanceof IASTProblemExpression) { |
| } else if (expr instanceof IASTTypeIdExpression) { |
| } else if (expr instanceof IASTUnaryExpression) { |
| IASTUnaryExpression uE = (IASTUnaryExpression) expr; |
| int op = uE.getOperator(); |
| if (op == IASTUnaryExpression.op_prefixIncr || op == IASTUnaryExpression.op_prefixDecr |
| || op == IASTUnaryExpression.op_postFixIncr || op == IASTUnaryExpression.op_postFixDecr) { |
| v1 = useDefMVMapping(uE.getOperand(), rhs, func, l1); |
| v2 = useDefMVMapping(uE.getOperand(), lhs, func, l2); |
| if (v1) { |
| Util.addAll(MVvar_, l2); |
| } |
| Util.addAll(set, l1); |
| Util.addAll(set, l2); |
| } else { |
| v1 = useDefMVMapping(uE.getOperand(), side, func, l1); |
| Util.addAll(set, l1); |
| } |
| return v1 | v2; |
| } else if (expr instanceof ICASTTypeIdInitializerExpression) { |
| } else { |
| } |
| return false; |
| } |
| |
| /** |
| * Returns true if statement is multi_valued. |
| */ |
| private boolean useDefMVMapping(IASTStatement stmt) { |
| if (stmt instanceof IASTDeclarationStatement) { |
| boolean value = false; |
| IASTDeclarationStatement declStmt = (IASTDeclarationStatement) stmt; |
| IASTDeclaration decl = declStmt.getDeclaration(); |
| if (decl instanceof IASTSimpleDeclaration) { |
| IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) decl; |
| IASTDeclarator[] declarators = simpleDecl.getDeclarators(); |
| for (int i = 0; i < declarators.length; i++) { |
| boolean v1 = false; |
| IASTInitializer init = declarators[i].getInitializer(); |
| if (init != null) { |
| IASTName name = declarators[i].getName(); |
| v1 = handleInitializer(init); |
| if (v1) { |
| if (!MVvar_.contains(name.toString())) { |
| MVvar_.add(name.toString()); |
| } |
| } |
| } |
| value = value | v1; |
| } |
| } |
| return value; |
| } else if (stmt instanceof IASTExpressionStatement) { |
| IASTExpressionStatement exprS = (IASTExpressionStatement) stmt; |
| IASTExpression expr = exprS.getExpression(); |
| List<String> mvlist = new ArrayList<String>(); |
| value = useDefMVMapping(expr, rhs, null, mvlist); |
| } |
| return false; |
| } |
| } |
| |
| class FuncParamMVChecker extends ASTVisitor { |
| protected MPICallGraphNode currentNode_; |
| protected MPIBlock block_; |
| protected MPICallGraphNode func; |
| |
| public FuncParamMVChecker(MPICallGraphNode func, MPIBlock block) { |
| currentNode_ = func; |
| block_ = block; |
| func = null; |
| } |
| |
| @Override |
| public int leave(IASTExpression expr) { |
| if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcExpr.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| if (cg_.getNode(currentNode_.getFileName(), signature) == func) { |
| func = null; |
| } |
| } |
| return PROCESS_CONTINUE; |
| } |
| |
| public void run() { |
| this.shouldVisitExpressions = true; |
| this.shouldVisitStatements = true; |
| |
| IASTNode content = block_.getContent(); |
| if (content != null) { |
| content.accept(this); |
| } |
| } |
| |
| @Override |
| public int visit(IASTExpression expr) { |
| if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcExpr.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| func = (MPICallGraphNode) cg_.getNode(currentNode_.getFileName(), signature); |
| if (func != null) { |
| IASTInitializerClause[] arguments = funcExpr.getArguments(); |
| for (int i = 0; i < arguments.length; i++) { |
| if (arguments[i] instanceof IASTExpression) { |
| ExprMVAnalyzer ema = new ExprMVAnalyzer(arguments[i], block_.getMVvar(), block_); |
| ema.run(); |
| if (ema.isMV()) { |
| String paramName = getFormalParamName(func, i); |
| if (paramName != null) { |
| func.getParamMV().put(paramName, new Boolean(true)); |
| } |
| } |
| } |
| } |
| } |
| } |
| return PROCESS_CONTINUE; |
| } |
| } |
| |
| class PointerAnalyzer extends ASTVisitor { |
| protected IBlock block_; |
| protected List<String> deref_; |
| protected List<String> addr_; |
| |
| public PointerAnalyzer(IBlock b) { |
| block_ = b; |
| deref_ = new ArrayList<String>(); |
| addr_ = new ArrayList<String>(); |
| } |
| |
| public List<String> getAddr() { |
| return addr_; |
| } |
| |
| public List<String> getDeref() { |
| return deref_; |
| } |
| |
| public void run() { |
| this.shouldVisitExpressions = true; |
| this.shouldVisitStatements = true; |
| IASTNode content = block_.getContent(); |
| if (content != null) { |
| content.accept(this); |
| } |
| } |
| |
| @Override |
| public int visit(IASTExpression expr) { |
| visitor(expr, false, false); |
| return PROCESS_SKIP; |
| } |
| |
| private void visitor(IASTExpression expr, boolean inDeref, boolean inAddr) { |
| if (expr instanceof IASTArraySubscriptExpression) { |
| IASTArraySubscriptExpression arrayE = (IASTArraySubscriptExpression) expr; |
| visitor(arrayE.getArrayExpression(), inDeref, inAddr); |
| visitor(arrayE.getSubscriptExpression(), false, false); |
| } else if (expr instanceof IASTBinaryExpression) { |
| IASTBinaryExpression biE = (IASTBinaryExpression) expr; |
| visitor(biE.getOperand1(), inDeref, inAddr); |
| visitor(biE.getOperand2(), inDeref, inAddr); |
| } else if (expr instanceof IASTConditionalExpression) { |
| IASTConditionalExpression condE = (IASTConditionalExpression) expr; |
| visitor(condE.getLogicalConditionExpression(), inDeref, inAddr); |
| visitor(condE.getPositiveResultExpression(), inDeref, inAddr); |
| visitor(condE.getNegativeResultExpression(), inDeref, inAddr); |
| } else if (expr instanceof IASTExpressionList) { |
| IASTExpressionList listE = (IASTExpressionList) expr; |
| IASTExpression[] exprs = listE.getExpressions(); |
| for (int i = 0; i < exprs.length; i++) { |
| visitor(exprs[i], inDeref, inAddr); |
| } |
| } else if (expr instanceof IASTFieldReference) { |
| IASTFieldReference fr = (IASTFieldReference) expr; |
| visitor(fr.getFieldOwner(), inDeref, inAddr); |
| } else if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcE = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcE.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| ICallGraphNode n = cg_.getNode(currentNode_.getFileName(), signature); |
| if (n != null) { |
| return; |
| } |
| visitor(funcE.getFunctionNameExpression(), false, false); |
| for (IASTInitializerClause argument: funcE.getArguments()) { |
| if (argument instanceof IASTExpression) { |
| visitor((IASTExpression) argument, inDeref, inAddr); |
| } |
| } |
| } else if (expr instanceof IASTIdExpression) { |
| IASTIdExpression ID = (IASTIdExpression) expr; |
| String var = ID.getName().toString(); |
| if (inDeref) { |
| if (!deref_.contains(var)) { |
| deref_.add(var); |
| } |
| } |
| if (inAddr) { |
| if (!addr_.contains(var)) { |
| addr_.add(var); |
| } |
| } |
| } else if (expr instanceof IASTUnaryExpression) { |
| IASTUnaryExpression uE = (IASTUnaryExpression) expr; |
| int op = uE.getOperator(); |
| boolean addrflag = inAddr; |
| boolean derefflag = inDeref; |
| if (op == IASTUnaryExpression.op_amper) { // &E |
| addrflag = true; |
| } else if (op == IASTUnaryExpression.op_star) { // *E |
| derefflag = true; |
| } |
| visitor(uE.getOperand(), addrflag, derefflag); |
| } |
| } |
| } |
| |
| class SeedsCollector extends ASTVisitor { |
| private MPICallGraphNode currentFunc_; |
| |
| public void run() { |
| this.shouldVisitExpressions = true; |
| this.shouldVisitStatements = true; |
| |
| for (ICallGraphNode n = cg_.botEntry(); n != null; n = n.botNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked) { |
| continue; |
| } |
| currentFunc_ = node; |
| IControlFlowGraph cfg = node.getCFG(); |
| for (IBlock b = cfg.getEntry(); b != null; b = b.topNext()) { |
| IASTNode content = b.getContent(); |
| if (content != null) { |
| content.accept(this); |
| } |
| } |
| } |
| for (ICallGraphNode n = cg_.botEntry(); n != null; n = n.botNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked) { |
| continue; |
| } |
| if (node.hasSeed()) { |
| for (Iterator<ICallGraphNode> i = node.getCallers().iterator(); i.hasNext();) { |
| MPICallGraphNode caller = (MPICallGraphNode) i.next(); |
| caller.setSeed(true); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public int visit(IASTExpression expr) { |
| if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcExpr.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| if (signature.equals("MPI_Comm_rank")) { //$NON-NLS-1$ |
| currentFunc_.setSeed(true); |
| } |
| } |
| return PROCESS_CONTINUE; |
| } |
| } |
| |
| /** |
| * Work list contains two kinds of blocks:<br> |
| * (1) where MPI_Comm_rank() is directly or indirectly called; <br> |
| * (2) the entry block of a function that has some MV real parameters; |
| * <p> |
| * (1) is marked in SeedsCollector and collected in WorkListCollector <br> |
| * (2) is collected in the slicing function. |
| */ |
| class WorkListCollector extends ASTVisitor { |
| private final ICallGraphNode func_; |
| private boolean inRankFunc; |
| private IASTExpressionList paramsOLD; |
| private IASTInitializerClause[] params_;// BRT will perhaps replace |
| // IASTExpressionList |
| private final LinkedList<IBlock> wlist; |
| private MPIBlock currentBlock_; |
| |
| public WorkListCollector(ICallGraphNode func) { |
| func_ = func; |
| inRankFunc = false; |
| wlist = new LinkedList<IBlock>(); |
| } |
| |
| public LinkedList<IBlock> getWorkList() { |
| if (!((MPICallGraphNode) func_).hasSeed()) { |
| return wlist; |
| } |
| |
| this.shouldVisitExpressions = true; |
| this.shouldVisitStatements = true; |
| for (IBlock b = func_.getCFG().getEntry(); b != null; b = b.topNext()) { |
| currentBlock_ = (MPIBlock) b; |
| IASTNode content = b.getContent(); |
| if (content != null) { |
| content.accept(this); |
| } |
| } |
| return wlist; |
| } |
| |
| @Override |
| public int leave(IASTExpression expr) { |
| if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcExpr.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| if (signature.equals("MPI_Comm_rank")) { //$NON-NLS-1$ |
| inRankFunc = false; |
| } |
| params_ = null; // BRT ???? do we do this here since no more |
| // IASTExpressionList below? |
| paramsOLD = null; |
| // BRT do we need to do paramsOLD=null instead? |
| // BRTnext IASTFunctionCallExpr is one level higher in the AST |
| // than the old IASTExpressionList was |
| |
| } else if (expr instanceof IASTExpressionList) { |
| paramsOLD = null;// BRT will never reach here, |
| // IASTExpressionLlist no longer in AST tree |
| } |
| return PROCESS_CONTINUE; |
| } |
| |
| // int visitDebugCount=0; |
| @Override |
| public int visit(IASTExpression expr) { |
| // System.out.println("visitDebugCount="+visitDebugCount+" expr="+expr+" "+expr.getRawSignature()); |
| // visitDebugCount++; |
| if (expr instanceof IASTFunctionCallExpression) { |
| IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression) expr; |
| IASTExpression funcname = funcExpr.getFunctionNameExpression(); |
| String signature = funcname.getRawSignature(); |
| if (signature.equals("MPI_Comm_rank")) { //$NON-NLS-1$ |
| inRankFunc = true; |
| } else { |
| MPICallGraphNode n = (MPICallGraphNode) cg_.getNode(currentNode_.getFileName(), signature); |
| if (n != null && n.hasSeed()) { |
| if (!wlist.contains(currentBlock_)) { |
| wlist.add(currentBlock_); |
| } |
| List<String> genMV = n.getMVSummary().get(signature); |
| Util.addAll(currentBlock_.getMVvar(), genMV); |
| if (currentBlock_.getMVvar().contains(n.getFuncName())) { |
| currentBlock_.getMVvar().remove(n.getFuncName()); |
| } |
| } |
| } |
| if (inRankFunc) { |
| // BRT do what was formerly done when we hit an |
| // IASTExpressionList node. |
| IASTInitializerClause[] initClause = funcExpr.getArguments(); |
| params_ = initClause; |
| } |
| |
| } else if (expr instanceof IASTIdExpression) { // BRT NOTE: most of |
| // changes (for CDT |
| // 7.0 change) are |
| // here |
| ((IASTIdExpression) expr).getName().toString(); |
| // BRT debug cond bkpt here: var2.equals("my_rank") |
| if (inRankFunc) { |
| IASTNode me = expr; |
| IASTNode parent = me.getParent(); |
| while (true) { |
| // if(parent == params) break; // BRT ptp40: params is |
| // null. not in ptp30; there is no longer an ASTnode for |
| // the parameters |
| // else |
| if (parent instanceof IASTFunctionCallExpression) { |
| break; |
| } else { |
| if (traceOn) { |
| System.out.println("MMVA: me=parent, parent=parent.getParent()"); //$NON-NLS-1$ |
| } |
| me = parent; |
| parent = parent.getParent(); |
| } |
| } |
| me.getRawSignature(); |
| boolean temp = false;// BRT never encountered now? |
| if (temp && !(parent instanceof IASTExpressionList /* |
| * new: |
| * || |
| * parent |
| * instanceof |
| * IASTFunctionCallExpression |
| */)) { |
| return PROCESS_CONTINUE; |
| // IASTExpression[] rankParams = |
| // params.getExpressions(); |
| } |
| |
| if (params_ != null) { |
| IASTInitializerClause cl = params_[0]; |
| if (cl instanceof IASTIdExpression) { |
| //System.out.println("IASTInitializerClause is IASTIdExpression"); //$NON-NLS-1$ |
| } |
| } |
| |
| int index; |
| for (index = 0; index < params_.length; index++) { |
| // if(me == rankParams[index]) break; |
| if (me == params_[index]) { |
| break; |
| } |
| } |
| // BRT The second arg of MPI_Comm_rank is the variable that |
| // is thus multi-valued. |
| if (index == 1) { |
| IASTIdExpression id = (IASTIdExpression) expr; |
| String var = id.getName().toString(); |
| // if(var.equals("MPI_Comm_rank")) return |
| // PROCESS_CONTINUE; |
| // BRT Add this variable to the list of multivalued |
| // variables in the current block, if not already there |
| if (!currentBlock_.getMVvar().contains(var)) { |
| currentBlock_.getMVvar().add(var); |
| } |
| if (!wlist.contains(currentBlock_)) { |
| wlist.add(currentBlock_); |
| } |
| } |
| } |
| } else if (expr instanceof IASTExpressionList) { |
| if (inRankFunc) { |
| paramsOLD = (IASTExpressionList) expr;// BRT investigate if |
| // ptp40 gets here |
| } |
| } |
| return PROCESS_CONTINUE; |
| } |
| } |
| |
| protected ICallGraph cg_; |
| |
| protected MPICallGraphNode currentNode_; |
| |
| protected final int lhs = 0; |
| |
| protected final int rhs = 1; |
| |
| protected boolean changed = false; |
| |
| private static final boolean traceOn = false; |
| |
| public MPIMVAnalysis(ICallGraph cg) { |
| cg_ = cg; |
| } |
| |
| public void run() { |
| init(); |
| SeedsCollector sc = new SeedsCollector(); |
| sc.run(); |
| functionMVSummary(); |
| functionSlicing(); |
| exprMVAnalysis(); |
| |
| for (ICallGraphNode n = cg_.topEntry(); n != null; n = n.topNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked) { |
| continue; |
| } |
| IControlFlowGraph cfg = node.getCFG(); |
| for (IBlock b = cfg.getEntry(); b != null; b = b.topNext()) { |
| MPIBlock block = (MPIBlock) b; |
| if (block.getMV() && (block.withBreak || block.withContinue)) { |
| System.out.println("************ Multi-valued branch with Break/Continue in " + //$NON-NLS-1$ |
| node.getFuncName() + "(" + node.getFileName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |
| } |
| |
| private void clean() { |
| for (IBlock b = currentNode_.getCFG().getEntry(); b != null; b = b.topNext()) { |
| MPIBlock block = (MPIBlock) b; |
| block.sliced = false; |
| block.setMVvar(new ArrayList<String>()); |
| } |
| } |
| |
| /** Determine whether an "EXPRESSION" is multi-valued */ |
| private void exprMVAnalysis() { |
| for (ICallGraphNode n = cg_.botEntry(); n != null; n = n.botNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked) { |
| continue; |
| } |
| IControlFlowGraph cfg = node.getCFG(); |
| for (IBlock b = cfg.getEntry(); b != null; b = b.topNext()) { |
| MPIBlock block = (MPIBlock) b; |
| //System.out.println("expMVAnalysis(): Block " + block.getID()); //$NON-NLS-1$ |
| ExprMVAnalyzer EA = new ExprMVAnalyzer(block.getContent(), block.getMVvar(), block); |
| // ^^^ BRT isEmpty |
| EA.run(); |
| EA.isMV(); |
| block.setMV(EA.isMV()); |
| |
| } |
| } |
| } |
| |
| private void functionMVSummary() { |
| changed = true; |
| while (changed) { |
| changed = false; |
| for (ICallGraphNode n = cg_.botEntry(); n != null; n = n.botNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked) { |
| continue; |
| } |
| currentNode_ = node; |
| for (Enumeration<String> e = node.getMVSummary().keys(); e.hasMoreElements();) { |
| String var = e.nextElement(); |
| singleVariableSlicing(var); |
| /* |
| * System.out.print("Summary: "); for(Iterator i = |
| * ((ArrayList)node.getMVSummary().get(var)).iterator(); |
| * i.hasNext();){ System.out.print((String)i.next() + ", "); |
| * } System.out.println(" "); |
| */ |
| clean(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Determines a set of multi-valued "VARIABLES" (local and global) in each |
| * program point |
| */ |
| private void functionSlicing() { |
| for (ICallGraphNode n = cg_.topEntry(); n != null; n = n.topNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked) { |
| continue; |
| } |
| currentNode_ = node; |
| // System.out.println(node.getFuncName()); |
| IControlFlowGraph cfg = node.getCFG(); |
| |
| /** |
| * The initial worklist contains seeds blocks in this function and |
| * the entry block if any of its parameters is multi-valued. |
| */ |
| WorkListCollector wlc = new WorkListCollector(currentNode_); |
| LinkedList<IBlock> seeds = wlc.getWorkList(); |
| boolean hasMVparam = false; |
| for (Enumeration<String> e = node.getParamMV().keys(); e.hasMoreElements();) { |
| String param = e.nextElement(); |
| boolean val = node.getParamMV().get(param).booleanValue(); |
| if (val) { // multi-valued parameter |
| ((MPIBlock) cfg.getEntry()).getMVvar().add(param); |
| hasMVparam = true; |
| } |
| } |
| if (hasMVparam) { |
| seeds.add(cfg.getEntry()); |
| } |
| |
| /** Slicing */ |
| while (!seeds.isEmpty()) { |
| MPIBlock block = (MPIBlock) seeds.remove(); |
| if (block.sliced) { |
| continue; |
| } |
| block.sliced = true; |
| |
| // System.out.println("current seed is " + block.getID()); |
| Hashtable<String, List<IBlock>> DUSucc = block.getDUSucc(); |
| List<String> mv = block.getMVvar(); |
| List<String> newMV = new ArrayList<String>(); |
| |
| handlePointers(block, mv); |
| |
| /* |
| * Intra-block slicing (Case #1) --- If there is a \phi function |
| * in this block, consider two cases: (1) If this block is a |
| * join block for If statement or Switch statement, or if this |
| * block is break exit join block of a loop, then all \phi |
| * variables in this block are multi-valued; (2) If this block |
| * is a join block (i.e., cond block) for For statement, While |
| * statement or Do statement, then its multi-valued \phi |
| * variables have been already marked through data dependences, |
| * and all used \phi variables are kept multi-valued. Note: a |
| * block falls into one and only one of these two cases. |
| */ |
| if (!block.getPhiVar().isEmpty()) { |
| List<IBlock> cond = block.getCond(); |
| int blockcase = 0; |
| for (Iterator<IBlock> i = cond.iterator(); i.hasNext();) { |
| if (blockcase == 2) { |
| break; |
| } |
| MPIBlock condblock = (MPIBlock) i.next(); |
| IASTStatement parent = condblock.getParent(); |
| if (parent instanceof IASTIfStatement || parent instanceof IASTSwitchStatement) { |
| blockcase = 1; |
| } else if (parent instanceof IASTForStatement || parent instanceof IASTDoStatement |
| || parent instanceof IASTWhileStatement) { |
| if (block.getType() == MPIBlock.exit_join_type) { |
| blockcase = 1; |
| } else if (block.getType() == MPIBlock.expr_type) { |
| blockcase = 2; |
| } |
| } |
| } |
| if (blockcase == 1) { |
| newMV = Util.Union(newMV, block.getPhiVar()); |
| } else if (blockcase == 2) { |
| for (Iterator<IBlock> i = cond.iterator(); i.hasNext();) { |
| MPIBlock condblock = (MPIBlock) i.next(); |
| for (Iterator<String> ii = condblock.getUsedPhiVar().iterator(); ii.hasNext();) { |
| String var = ii.next(); |
| if (mv.contains(var)) { |
| newMV.add(var); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Intra-block slicing (Case #1) --- Given MV/SV used variable, |
| * determine whether defined variables are MV or SV. |
| */ |
| |
| IASTNode content = block.getContent(); |
| ExprMVAnalyzer emva = new ExprMVAnalyzer(content, mv, block); |
| emva.run(); |
| newMV = Util.Union(newMV, emva.getMVList()); |
| |
| /** |
| * Intra-block slicing (Case #3) -- any used only multi-valued |
| * variable is still multi-valued |
| */ |
| for (Iterator<String> i = mv.iterator(); i.hasNext();) { |
| String var = i.next(); |
| if (block.getUse().contains(var) && !block.getDef().contains(var)) { |
| if (!newMV.contains(var)) { |
| newMV.add(var); |
| } |
| } |
| } |
| |
| handlePointers(block, newMV); |
| handleBroadCast(block, newMV); |
| block.setMVvar(newMV); |
| |
| /** Inter-block slicing based on data dependences */ |
| for (Iterator<String> i = newMV.iterator(); i.hasNext();) { |
| String MVvar = i.next(); |
| List<IBlock> DUnext = DUSucc.get(MVvar); |
| if (DUnext != null) { |
| for (Iterator<IBlock> ii = DUnext.iterator(); ii.hasNext();) { |
| MPIBlock b = (MPIBlock) ii.next(); |
| if (b.sliced == true) { |
| continue; |
| } |
| if (!seeds.contains(b)) { |
| seeds.add(b); |
| // System.out.println("block " + b.getID() + |
| // " is added to seeds"); |
| } |
| if (!b.getMVvar().contains(MVvar)) { |
| b.getMVvar().add(MVvar); |
| } |
| } |
| } |
| } |
| |
| /** Inter-block slicing based on \Phi edges */ |
| for (Iterator<IBlock> i = block.getJoin().iterator(); i.hasNext();) { |
| MPIBlock join = (MPIBlock) i.next(); |
| if (!seeds.contains(join) && !join.sliced) { |
| seeds.add(join); |
| } |
| } |
| } |
| |
| /* |
| * Function Multi-valued Summary --- (1) whether a function's REAL |
| * parameters are multi-valued (A real parameter of function foo is |
| * multi-valued if in any of foo's call sites the parameter is |
| * multi-valued) |
| */ |
| for (IBlock block = cfg.getEntry(); block != null; block = block.topNext()) { |
| FuncParamMVChecker fpc = new FuncParamMVChecker(node, (MPIBlock) block); |
| fpc.run(); |
| } |
| } |
| } |
| |
| private String getFormalParamName(ICallGraphNode func, int index) { |
| IASTFunctionDefinition fd = func.getFuncDef(); |
| IASTFunctionDeclarator fdecl = fd.getDeclarator(); |
| if (fdecl instanceof IASTStandardFunctionDeclarator) { |
| IASTStandardFunctionDeclarator sfunc = (IASTStandardFunctionDeclarator) fdecl; |
| IASTParameterDeclaration[] params = sfunc.getParameters(); |
| if (index >= params.length) { |
| return null; |
| } |
| IASTName param = params[index].getDeclarator().getName(); |
| return param.toString(); |
| } else { |
| ICASTKnRFunctionDeclarator krfunc = (ICASTKnRFunctionDeclarator) fdecl; |
| IASTName[] params = krfunc.getParameterNames(); |
| if (index >= params.length) { |
| return null; |
| } |
| return params[index].toString(); |
| } |
| } |
| |
| private void handleBroadCast(MPIBlock block, List<String> set) { |
| BroadCastAnalyzer bca = new BroadCastAnalyzer(block); |
| bca.run(); |
| String bcdata = bca.getBCdata(); |
| if (bcdata != null) { |
| if (set.contains(bcdata)) { |
| set.remove(bcdata); |
| } |
| } |
| block.setMVvar(set); |
| } |
| |
| private void handlePointers(MPIBlock block, List<String> set) { |
| PointerAnalyzer pa = new PointerAnalyzer(block); |
| pa.run(); |
| for (Iterator<String> i = pa.getAddr().iterator(); i.hasNext();) { |
| String var = i.next(); |
| if (block.getUse().contains(var)) { |
| if (!set.contains(var)) { |
| set.add(var); |
| } |
| } |
| } |
| for (Iterator<String> i = pa.getDeref().iterator(); i.hasNext();) { |
| String var = i.next(); |
| if (block.getUse().contains(var)) { |
| if (!set.contains(var)) { |
| set.add(var); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Initialize all parameters of a function as single-valued; Initialize its |
| * MV and SV summary as empty |
| */ |
| private void init() { |
| for (ICallGraphNode n = cg_.topEntry(); n != null; n = n.topNext()) { |
| MPICallGraphNode node = (MPICallGraphNode) n; |
| if (!node.marked) { |
| continue; |
| } |
| IASTFunctionDefinition fd = node.getFuncDef(); |
| IASTFunctionDeclarator fdecl = fd.getDeclarator(); |
| if (fdecl instanceof IASTStandardFunctionDeclarator) { |
| IASTStandardFunctionDeclarator sfunc = (IASTStandardFunctionDeclarator) fdecl; |
| IASTParameterDeclaration[] params = sfunc.getParameters(); |
| for (int i = 0; i < params.length; i++) { |
| IASTName param = params[i].getDeclarator().getName(); |
| if (param.toString().equals("")) { |
| continue; //void parameter //$NON-NLS-1$ |
| } |
| node.getParamMV().put(param.toString(), new Boolean(false)); |
| node.getMVSummary().put(param.toString(), new ArrayList<String>()); |
| } |
| } else { |
| ICASTKnRFunctionDeclarator krfunc = (ICASTKnRFunctionDeclarator) fdecl; |
| IASTName[] params = krfunc.getParameterNames(); |
| for (int i = 0; i < params.length; i++) { |
| node.getParamMV().put(params[i].toString(), new Boolean(false)); |
| node.getMVSummary().put(params[i].toString(), new ArrayList<String>()); |
| } |
| } |
| for (Iterator<String> i = node.getGlobalUse().iterator(); i.hasNext();) { |
| String var = i.next(); |
| node.getMVSummary().put(var, new ArrayList<String>()); |
| } |
| /* |
| * Another entry if (1) the function has no parameter and no global |
| * use; (2) all parameters and global uses are SV. (We call this |
| * function(context) as "empty MV input" function(context).) Use the |
| * function name as the key in these cases |
| */ |
| node.getMVSummary().put(node.getFuncName(), new ArrayList<String>()); |
| } |
| } |
| |
| /** |
| * The return value of a function is multi-valued if any of its return |
| * statement is multi-valued. |
| */ |
| private boolean returnMV() { |
| boolean returnmv = false; |
| for (Iterator<IBlock> i = ((MPIControlFlowGraph) currentNode_.getCFG()).getReturnBlocks().iterator(); i.hasNext();) { |
| MPIBlock returnBlock = (MPIBlock) i.next(); |
| ExprMVAnalyzer ema = new ExprMVAnalyzer(returnBlock.getContent(), returnBlock.getMVvar(), returnBlock); |
| ema.run(); |
| returnmv = returnmv | ema.isMV(); |
| returnBlock.setMV(false); // reset it |
| } |
| return returnmv; |
| } |
| |
| /** |
| * For each function, assume all parameters are MV, find out which global |
| * variables (and passable parameters) are MV |
| */ |
| private void singleVariableSlicing(String var) { |
| IControlFlowGraph cfg = currentNode_.getCFG(); |
| |
| WorkListCollector wlc = new WorkListCollector(currentNode_); |
| LinkedList<IBlock> seeds = wlc.getWorkList(); |
| if (!var.equals(currentNode_.getFuncName())) { |
| seeds.add(cfg.getEntry()); |
| ((MPIBlock) cfg.getEntry()).getMVvar().add(var); |
| } |
| |
| while (!seeds.isEmpty()) { |
| MPIBlock block = (MPIBlock) seeds.remove(); |
| if (block.sliced) { |
| continue; |
| } |
| block.sliced = true; |
| |
| if (block.getContent() == null) { |
| continue; |
| } |
| |
| Hashtable<String, List<IBlock>> DUSucc = block.getDUSucc(); |
| List<String> mv = block.getMVvar(); |
| List<String> newMV = new ArrayList<String>(); |
| |
| handlePointers(block, mv); |
| |
| if (!block.getPhiVar().isEmpty()) { |
| List<IBlock> cond = block.getCond(); |
| int blockcase = 0; |
| for (Iterator<IBlock> i = cond.iterator(); i.hasNext();) { |
| if (blockcase == 2) { |
| break; |
| } |
| MPIBlock condblock = (MPIBlock) i.next(); |
| IASTStatement parent = condblock.getParent(); |
| if (parent instanceof IASTIfStatement || parent instanceof IASTSwitchStatement) { |
| blockcase = 1; |
| } else if (parent instanceof IASTForStatement || parent instanceof IASTDoStatement |
| || parent instanceof IASTWhileStatement) { |
| if (block.getType() == MPIBlock.exit_join_type) { |
| blockcase = 1; |
| } else if (block.getType() == MPIBlock.expr_type) { |
| blockcase = 2; |
| } |
| } |
| } |
| if (blockcase == 1) { |
| newMV = Util.Union(newMV, block.getPhiVar()); |
| } else if (blockcase == 2) { |
| for (Iterator<IBlock> i = cond.iterator(); i.hasNext();) { |
| MPIBlock condblock = (MPIBlock) i.next(); |
| for (Iterator<String> ii = condblock.getUsedPhiVar().iterator(); ii.hasNext();) { |
| String v = ii.next(); |
| if (mv.contains(v)) { |
| newMV.add(v); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Intra-block slicing (Case #1) --- Given MV/SV used variable, |
| * determine whether defined variables are MV or SV. |
| */ |
| |
| IASTNode content = block.getContent(); |
| ExprMVAnalyzer emva = new ExprMVAnalyzer(content, mv, block); |
| emva.run(); |
| newMV = Util.Union(newMV, emva.getMVList()); |
| |
| /** |
| * Intra-block slicing (Case #3) -- any used only multi-valued |
| * variable is still multi-valued |
| */ |
| for (Iterator<String> i = mv.iterator(); i.hasNext();) { |
| String v = i.next(); |
| if (block.getUse().contains(v) && !block.getDef().contains(v)) { |
| if (!newMV.contains(v)) { |
| newMV.add(v); |
| } |
| } |
| } |
| |
| handlePointers(block, newMV); |
| handleBroadCast(block, newMV); |
| block.setMVvar(newMV); |
| |
| /** Inter-block slicing based on data dependences */ |
| for (Iterator<String> i = newMV.iterator(); i.hasNext();) { |
| String MVvar = i.next(); |
| List<IBlock> DUnext = DUSucc.get(MVvar); |
| if (DUnext != null) { |
| for (Iterator<IBlock> ii = DUnext.iterator(); ii.hasNext();) { |
| MPIBlock b = (MPIBlock) ii.next(); |
| if (b.sliced == true) { |
| continue; |
| } |
| if (!seeds.contains(b)) { |
| seeds.add(b); |
| // System.out.println("block " + b.getID() + |
| // " is added to seeds"); |
| } |
| if (!b.getMVvar().contains(MVvar)) { |
| b.getMVvar().add(MVvar); |
| } |
| } |
| } |
| } |
| |
| /** Inter-block slicing based on \Phi edges */ |
| for (Iterator<IBlock> i = block.getJoin().iterator(); i.hasNext();) { |
| MPIBlock join = (MPIBlock) i.next(); |
| if (!seeds.contains(join) && !join.sliced) { |
| seeds.add(join); |
| } |
| } |
| } |
| |
| List<String> MVlist = currentNode_.getMVSummary().get(var); |
| for (Iterator<String> i = currentNode_.getGlobalDef().iterator(); i.hasNext();) { |
| String v = i.next(); |
| if (((MPIBlock) cfg.getExit()).getMVvar().contains(v)) { |
| if (!MVlist.contains(v)) { |
| MVlist.add(v); |
| } |
| } |
| } |
| for (Iterator<String> i = currentNode_.getParamDef().iterator(); i.hasNext();) { |
| String v = i.next(); |
| if (((MPIBlock) cfg.getExit()).getMVvar().contains(v)) { |
| if (!MVlist.contains(v)) { |
| MVlist.add(v); |
| } |
| } |
| } |
| |
| if (returnMV()) { |
| if (!MVlist.contains(currentNode_.getFuncName())) { |
| MVlist.add(currentNode_.getFuncName()); |
| } |
| } |
| } |
| |
| } |