package cd.transform.optimizers; import cd.ir.Ast; import cd.ir.Ast.*; import cd.ir.BasicBlock; import cd.ir.ControlFlowGraph; import cd.ir.ExprVisitor; import cd.ir.Symbol.VariableSymbol; import cd.transform.analysis.LiveVarAnalysis; import java.util.*; public class WriteOnlyVarRemoval extends OptimizerVisitor> { @Override public boolean go(ControlFlowGraph cfg) { LiveVarAnalysis analysis = new LiveVarAnalysis(cfg); for (BasicBlock block : cfg.allBlocks) { Set state = new HashSet<>(analysis.outStateOf(block)); if (block.condition != null) new LiveVarAnalysis.Visitor().visit(block.condition, state); for (ListIterator iterator = block.stmts.listIterator(block.stmts.size()); iterator.hasPrevious(); ) { Stmt stmt = iterator.previous(); Ast res = visit(stmt, state); // TODO: this code should work? even if we iterate through the newly created Stmt nodes if (stmt != res) { iterator.remove(); assert res instanceof Seq; Seq seq = (Seq) res; for (Ast ast : seq.rwChildren) { assert ast instanceof Stmt; iterator.add((Stmt) ast); } nodeReplaced(stmt, res); } } } return hasChanged(); } @Override public Ast assign(Assign ast, Set arg) { if (ast.left() instanceof Var && !arg.contains(((Var) ast.left()).sym)) { List methodCalls = new ArrayList<>(); new MethodCallFinder().visit(ast.right(), methodCalls); return new Seq(methodCalls); } else { return ast; } } private class MethodCallFinder extends ExprVisitor> { @Override public Void methodCall(Ast.MethodCallExpr ast, List arg) { arg.add(new MethodCall(ast)); return null; } } }