public void updateKillGenSet(String methodName, QuadrupletStmt stmt, BlockDataFlowState bFlow) { if (stmt == null) return; BitSet out = bFlow.getOut(); BitSet gen = bFlow.getGen(); BitSet kill = bFlow.getKill(); for (Name name : this.uniqueGlobals.get(methodName)) { int i = this.uniqueGlobals.get(methodName).indexOf(name); boolean resetName = false; if (name.isArray()) { Name myName = name; do { ArrayName array = (ArrayName) myName; if (array.getIndex().equals(stmt.getDestination())) { // Index being reassigned, KILL! resetName = true; } myName = array.getIndex(); } while (myName.isArray()); if (stmt.getDestination().isArray()) { ArrayName dest = (ArrayName) stmt.getDestination(); ArrayName arrName = (ArrayName) name; if (dest.getIndex().getClass().equals(ConstantName.class) && !arrName.getIndex().getClass().equals(ConstantName.class)) { if (arrName.getId().equals(dest.getId())) { resetName = true; } } } } if (resetName) { if (out.get(i)) { kill.set(i); } gen.clear(i); } if (name.equals(stmt.getDestination())) { gen.set(i); } } }
private void calculateGenKillSets(CFGBlock block, BlockDataFlowState bFlow) { for (int i = block.getStatements().size() - 1; i >= 0; i--) { LIRStatement stmt = block.getStatements().get(i); if (stmt.getClass().equals(QuadrupletStmt.class)) { QuadrupletStmt qStmt = (QuadrupletStmt) stmt; if (!qStmt.getDestination().getClass().equals(RegisterName.class)) { updateKillGenSet(block.getMethodName(), qStmt, bFlow); } } else if (stmt.getClass().equals(StoreStmt.class)) { updateKillGenSet(block.getMethodName(), (StoreStmt) stmt, bFlow); } else if (stmt.getClass().equals(CallStmt.class)) { updateKillGenSet(block.getMethodName(), (CallStmt) stmt, bFlow); } } }
private void initialize(String methodName) { this.cfgBlocksToProcess.clear(); HashSet<Name> temp = new HashSet<Name>(); for (CFGBlock block : this.mMap.get(methodName).getCfgBlocks()) { List<LIRStatement> blockStmts = block.getStatements(); for (int i = 0; i < blockStmts.size(); i++) { LIRStatement stmt = blockStmts.get(i); if (stmt.getClass().equals(QuadrupletStmt.class)) { QuadrupletStmt qStmt = (QuadrupletStmt) stmt; if (qStmt.getDestination().isGlobal()) temp.add(qStmt.getDestination()); } else if (stmt.getClass().equals(StoreStmt.class)) { StoreStmt sStmt = (StoreStmt) stmt; temp.add(sStmt.getVariable()); } } this.cfgBlocksToProcess.add(block); } this.uniqueGlobals.put(methodName, new ArrayList<Name>()); this.uniqueGlobals.get(methodName).addAll(temp); }
// For each use of a Name, see all the reaching definitions for that Name // If there exists only ONE reaching assignment definition that assigns to Name, // replace Name with definition's LHS private Name copyPropagateOnArg(Name arg, BlockDataFlowState bFlow) { if (arg != null) { HashMap<Name, HashSet<QuadrupletStmt>> nameToStmtsThatAssignIt = assignmentDefGenerator.getNameToQStmtsThatAssignIt(); BitSet in = bFlow.getIn(); HashSet<QuadrupletStmt> stmtsAssigningName; QuadrupletStmt reachingAssignmentStmt = null; int numReachingDefs; stmtsAssigningName = nameToStmtsThatAssignIt.get(arg); numReachingDefs = 0; if (stmtsAssigningName != null) { for (QuadrupletStmt qs : stmtsAssigningName) { if (in.get(qs.getMyId())) { numReachingDefs++; reachingAssignmentStmt = qs; } } if (numReachingDefs == 1) { // There is exactly one assignment statement reaching this block // so we can perform copy propagation // Return the name which we should replace the arg with return reachingAssignmentStmt.getArg1(); } } // Check if Name is ArrayName and try to optimize index if (arg.getClass().equals(ArrayName.class)) { Name arrIndex = ((ArrayName) arg).getIndex(); Name propagatedName = copyPropagateOnArg(arrIndex, bFlow); if (propagatedName != null) { ((ArrayName) arg).setIndex(propagatedName); } } } return null; }
private void optimize(CFGBlock block) { BlockDataFlowState bFlow = assignmentDefGenerator.getBlockAssignReachingDefs().get(block); QuadrupletStmt qStmt; PopStmt popStmt; PushStmt pushStmt; CmpStmt cStmt; Name newArg1, newArg2, dest; for (LIRStatement stmt : block.getStatements()) { // Reset kill set bFlow.getKill().clear(); if (stmt.getClass().equals(CallStmt.class)) { CallStmt callStmt = (CallStmt) stmt; if (callStmt.getMethodLabel().equals(ProgramFlattener.exceptionHandlerLabel)) continue; // Update BlockDataFlowState kill set assignmentDefGenerator.invalidateFunctionCall(bFlow); // Update BlockDataFlowState in set by using updated kill set bFlow.getIn().xor(bFlow.getKill()); } else if (stmt.getClass().equals(QuadrupletStmt.class)) { qStmt = (QuadrupletStmt) stmt; newArg1 = copyPropagateOnArg(qStmt.getArg1(), bFlow); if (newArg1 != null) { qStmt.setArg1(newArg1); } newArg2 = copyPropagateOnArg(qStmt.getArg2(), bFlow); if (newArg2 != null) { qStmt.setArg2(newArg2); } dest = qStmt.getDestination(); if (dest != null) { // Check if dest is ArrayName and try to optimize index if (dest.getClass().equals(ArrayName.class)) { Name arrIndex = ((ArrayName) dest).getIndex(); Name propagatedName = copyPropagateOnArg(arrIndex, bFlow); if (propagatedName != null) ((ArrayName) dest).setIndex(propagatedName); } } // Update BlockDataFlowState kill set assignmentDefGenerator.updateKillGenSet(dest, bFlow); // Update BlockDataFlowState in set by using updated kill set bFlow.getIn().xor(bFlow.getKill()); // Optimize PopStmt } else if (stmt.getClass().equals(PopStmt.class)) { popStmt = (PopStmt) stmt; newArg1 = copyPropagateOnArg(popStmt.getName(), bFlow); if (newArg1 != null) { popStmt.setName(newArg1); } // Optimize PushStmt } else if (stmt.getClass().equals(PushStmt.class)) { pushStmt = (PushStmt) stmt; newArg1 = copyPropagateOnArg(pushStmt.getName(), bFlow); if (newArg1 != null) { pushStmt.setName(newArg1); } // Optimize CmpStmt } else if (stmt.getClass().equals(CmpStmt.class)) { cStmt = (CmpStmt) stmt; newArg1 = copyPropagateOnArg(cStmt.getArg1(), bFlow); if (newArg1 != null) { cStmt.setArg1(newArg1); } newArg2 = copyPropagateOnArg(cStmt.getArg2(), bFlow); if (newArg2 != null) { cStmt.setArg2(newArg2); } } } }