package de.gaalop.maple; import java.util.Stack; import de.gaalop.OptimizationException; import de.gaalop.OptimizationStrategy; import de.gaalop.cfg.AssignmentNode; import de.gaalop.cfg.ControlFlowGraph; import de.gaalop.cfg.EmptyControlFlowVisitor; import de.gaalop.cfg.LoopNode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * This strategy uses maple to lower the graph from GA to normal arithmetic using the default clifford base vectors * {e<sub>1</sub>, e<sub>2</sub>, e<sub>3</sub>, e<sub>4</sub>, e<sub>5</sub>}. Then, in a second step, it transforms * the graph in such a way that it uses the base vectors {e<sub>0</sub>, e<sub>1</sub>, e<sub>2</sub>, e<sub>3</sub>, * e<sub>inf</sub>} */ public class MapleStrategy implements OptimizationStrategy { private static class AssignmentCounter extends EmptyControlFlowVisitor { protected int totalAssignments; private int assignmentsInLoop; private Stack<LoopNode> loops = new Stack<LoopNode>(); AssignmentCounter() { } @Override public void visit(AssignmentNode node) { if (loops.isEmpty()) { totalAssignments++; } else { assignmentsInLoop++; } node.getSuccessor().accept(this); } @Override public void visit(LoopNode node) { int iterations = node.getIterations(); boolean unroll = iterations > 0; int previousNumber = assignmentsInLoop; if (unroll) { assignmentsInLoop = 0; loops.push(node); } node.getBody().accept(this); if (unroll) { loops.pop(); assignmentsInLoop *= iterations; if (loops.isEmpty()) { totalAssignments += assignmentsInLoop; } else { previousNumber += assignmentsInLoop; } assignmentsInLoop = previousNumber; } node.getSuccessor().accept(this); } } private Log log = LogFactory.getLog(MapleStrategy.class); private final MapleSimplifier simplifier; private final boolean constantFolding; MapleStrategy(MapleSimplifier simplifier, boolean constantFolding) { this.simplifier = simplifier; this.constantFolding = constantFolding; } @Override public void transform(ControlFlowGraph graph) throws OptimizationException { try { log.debug("Inlining macros"); InlineMacrosVisitor visitor = new InlineMacrosVisitor(); graph.accept(visitor); log.debug("Graph after macro inlining:\n" + graph.prettyPrint()); } catch (Exception e) { throw new OptimizationException("Unable to inline macros:\n" + e.getMessage(), e, graph); } try { AssignmentCounter counter = new AssignmentCounter(); graph.accept(counter); simplifier.notifyMaximum(counter.totalAssignments); } catch (Exception e) { throw new OptimizationException("Unable to count assignments in graph:\n" + e.getMessage(), graph); } try { log.debug("Simplifying graph using maple."); simplifier.simplify(graph); } catch (Exception e) { throw new OptimizationException("Unable to simplify using maple:\n" + e.getMessage(), e, graph); } try { log.debug("Removing unused variables."); RemoveUnusedVariablesVisitor visitor = new RemoveUnusedVariablesVisitor(); graph.accept(visitor); } catch (Exception e) { throw new OptimizationException("Unable to remove unused variables from graph:\n" + e.getMessage(), e, graph); } if (constantFolding) { try { log.debug("Folding constants."); ConstantFolding folder = new ConstantFolding(); graph.accept(folder); } catch (Exception e) { throw new OptimizationException("Unable to eliminate constants:\n" + e.getMessage(), e, graph); } } log.debug("Graph after optimizations:\n" + graph.prettyPrint()); } }