/** Perform the actual copy propagation. */ public void perform() { Stack<Chord> wl = WorkArea.<Chord>getStack("perform CP"); Chord start = scribble.getBegin(); boolean doSubscripts = scribble.scalarReplacementPerformed(); // If subscript addresses are propagated before scalar replacement // is performed, scalar replacement generates incorrect code. wl.push(start); Chord.nextVisit(); start.setVisited(); while (!wl.empty()) { Chord s = wl.pop(); s.pushOutCfgEdges(wl); if (s.isAssignChord()) { visitExprChord((ExprChord) s, doSubscripts); } } WorkArea.<Chord>returnStack(wl); if (rChanged) { scribble.recomputeRefs(); } }
/** * Return true if this is a legal loop. A legal loop contains no function calls and has no scalar * variable cycles. A cycle exists when the variable is referenced before it is defed. We go to * some trouble to allow loops containing cycles such as * * <pre> * s = s + a(i,j) * </pre> * * to be permuted. */ private boolean legalLoop(LoopHeaderChord loop) { Stack<Chord> wl = WorkArea.<Chord>getStack("legalLoop"); References refs = scribble.getRefs(); Chord.nextVisit(); wl.push(loop); loop.setVisited(); int n = loop.numLoopExits(); for (int i = 0; i < n; i++) loop.getLoopExit(i).setVisited(); boolean legal = true; outer: while (!wl.empty()) { Chord c = wl.pop(); if (c.getCall(true) != null) { legal = false; break; } if ((c instanceof DecisionChord) && (c != loop.getLoopTest())) { legal = false; break; } if (c.isAssignChord() && !c.isPhiExpr()) { ExprChord ec = (ExprChord) c; Expr lhs = ec.getLValue(); Expr rhs = ec.getRValue(); // The variable is both defed and used in the loop and // we don't know how it is used. For example, it could be // s = s + 1 // c(i,j) = s // or // c(i,j) = s // s = s + 1 // We want to allow // s = s + c(i,j) // because we know that s is not used to specify the // value of an array element. We want to allow // s = ... // = s // since there is no cycle. if (lhs instanceof LoadDeclAddressExpr) { LoadDeclAddressExpr ldae = (LoadDeclAddressExpr) lhs; VariableDecl vd = ldae.getDecl().returnVariableDecl(); if ((vd != null) && !loop.isLoopIndex(vd)) { boolean cycle = false; Iterator<Chord> it1 = refs.getUseChords(vd); while (it1.hasNext()) { Chord s = it1.next(); cycle |= (s == c); } Iterator<Chord> it2 = refs.getUseChords(vd); while (it2.hasNext()) { Chord s = it2.next(); if (c == s) continue; if (s.getLoopHeader() != loop) continue; if (cycle) { // There was a cycle and another use. // s = s + 1 // = s legal = false; break outer; } // Check for a use before the def. while (true) { s = s.getNextChord(); if (s == null) break; if (s == c) { legal = false; break outer; } } } } } } c.pushOutCfgEdges(wl); } WorkArea.<Chord>returnStack(wl); return legal; }
private void visitExprChord(ExprChord se, boolean doSubscripts) { if (se.getPredicate() != null) { return; } Expr rvalue = se.getRValue(); if (rvalue instanceof PhiExpr) { return; } if (rvalue instanceof DualExpr) { if (!doSubscripts && (((DualExpr) rvalue).getHigh() instanceof SubscriptExpr)) { return; // Don't mess up ScalarReplacement. } rvalue = ((DualExpr) rvalue).getLow(); } // Check if the statement is a simple assignment to a variable. Expr lvalue = se.getLValue(); if (!(lvalue instanceof LoadDeclAddressExpr)) { return; } if (!rvalue.getCoreType().isAtomicType()) { return; } LoadDeclAddressExpr lhs = (LoadDeclAddressExpr) lvalue; VariableDecl ldecl = (VariableDecl) lhs.getDecl(); if (ldecl.isNotAliasCandidate()) { return; } if (doSubscripts) { while (rvalue instanceof DualExpr) { rvalue = rvalue.getLow(); } } Expr rv = rvalue; while (rv.isCast()) { rv = rv.getOperand(0); } if (!(rv instanceof LoadDeclValueExpr)) { if (!(rv instanceof AdditionExpr) && !(rv instanceof SubtractionExpr)) { return; } if (!rv.optimizationCandidate()) { return; } BinaryExpr be = (BinaryExpr) rv; Expr ra = be.getRightArg(); if (!ra.isLiteralExpr()) { return; } if (!ra.getCoreType().isIntegerType()) { return; } Expr la = be.getLeftArg(); while (la.isCast()) { la = la.getOperand(0); } if (!(la instanceof LoadDeclValueExpr)) { return; // It's not a simple add or subtract. } // Undo some of the damage caused by ValNum & LICM. Move simple // adds & subtracts to reduce register pressure. // It makes no sense to propagate an addition expression that // references a variable that should not be aliased. For // example, if the variable is in memory, this could increase // the number of memory references and undo much of what global // variable replacement tries to do. VariableDecl org = ((VariableDecl) ((LoadDeclValueExpr) la).getDecl()).getOriginal(); if ((org == ldecl.getOriginal()) || org.isNotAliasCandidate()) { return; } LoopHeaderChord lh = be.getChord().getLoopHeader(); LoadExpr[] uda = se.getDefUseArray(); for (int i = 0; i < uda.length; i++) { LoadExpr ud = uda[i]; Chord s = ud.getChord(); LoopHeaderChord slh = s.getLoopHeader(); Note out = ud.getOutDataEdge(); // Propagate the expression. out.changeInDataEdge(ud, rvalue.copy()); ud.unlinkExpression(); rChanged = true; } return; } LoadDeclValueExpr rhs = (LoadDeclValueExpr) rv; VariableDecl rdecl = (VariableDecl) rhs.getDecl(); if (!rdecl.optimizationCandidate()) { return; } if ((rdecl == rdecl.getOriginal()) && (ldecl.getOriginal() == rdecl)) { return; // The original variable is special in SSA form. } ExprChord rhsud = rhs.getUseDef(); if (!doSubscripts && (rhsud != null)) { // Don't mess up scalar replacement by creating new data // dependence edges. Expr rhsv = rhsud.getRValue(); if (rhsv instanceof DualExpr) { return; } } // For now if the may use info is not null, do not propagate. if (rhs.getMayUse() != null) { return; } MayDef md = se.getMayDef(); LoadExpr[] uses = se.getDefUseArray(); for (int i = 0; i < uses.length; i++) { LoadExpr use = uses[i]; // Copy propagation of a variable into a phi function just // results in extra copy operations. For example, consider // x1 = y // l: x3 = phi(x1, x4) // // After copy propagation // x1 = y // l: x3 = phi(y, x4) // // After phi removal // x1 = y // x3 = y // l: // // After variable coalescing // x = y // x = y if (use.getOutDataEdge() instanceof PhiExpr) { continue; } boolean doit = true; // If there is may def information associated with the // lhs of the expression, check to see if it can be // propagated. if (!unsafe) { MayUse mu = use.getMayUse(); if (md != null) { if (mu == null) { doit = false; } else { Declaration d1 = null; MayDef ud = mu.findMayDef(); if (ud != null) { d1 = ((LoadExpr) (ud.getLhs())).getDecl(); } /*Declaration d1 = mu.getDecl();*/ Declaration d2 = ((LoadExpr) md.getLhs()).getDecl(); doit = (d1 == d2); } } } if (doit) { // Change the variable in the use. if (rv == rvalue) { use.setDecl(rdecl); use.setUseDef(rhsud); } else { Note out = use.getOutDataEdge(); out.changeInDataEdge(use, rvalue.copy()); use.unlinkExpression(); } rChanged = true; propagationCount++; } else { aliasInhibitedCount++; } } }