package de.gaalop.gapp.importing;
import de.gaalop.OptimizationException;
import de.gaalop.cfg.AssignmentNode;
import de.gaalop.cfg.ControlFlowGraph;
import de.gaalop.cfg.ControlFlowVisitor;
import de.gaalop.cfg.EmptyControlFlowVisitor;
import de.gaalop.cfg.StoreResultNode;
import de.gaalop.dfg.EmptyExpressionVisitor;
import de.gaalop.dfg.ExpressionVisitor;
import de.gaalop.dfg.MultivectorComponent;
import de.gaalop.dfg.Variable;
import de.gaalop.gapp.GAPP;
import de.gaalop.gapp.Variableset;
import de.gaalop.gapp.importing.optimization.GAPPFurtherOptimizationsFacade;
import de.gaalop.gapp.instructionSet.GAPPAssignInputsVector;
import de.gaalop.gapp.variables.GAPPScalarVariable;
import de.gaalop.gapp.variables.GAPPVector;
import de.gaalop.tba.Plugin;
import de.gaalop.tba.cfgImport.CFGImporterFacade;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
/**
* Facade class to decorate the ControlFlowGraph with GAPP instructions
* @author Christian Steinmetz
*/
public class GAPPDecoratingMain {
private de.gaalop.gapp.Plugin plugin;
public GAPPDecoratingMain(de.gaalop.gapp.Plugin plugin) {
this.plugin = plugin;
}
/**
* Decorates a given ControlFlowGraph with GAPP instructions
* @param graph The ControlFlowGraph
* @param optMaxima Should Maxima be used?
* @param maximaCommand The maxima command
* @return The same graph object (which is now decorated with GAPP instructions)
* @throws OptimizationException
*/
public ControlFlowGraph decorateGraph(ControlFlowGraph graph) throws OptimizationException {
//test if an variable inputsVector exists, if yes, throw an Exception,
//because inputsVector is used in the following conversion process.
Variable inputsVectorVar = new Variable("inputsVector");
if (
graph.getInputVariables().contains(inputsVectorVar) ||
graph.getScalarVariables().contains(inputsVectorVar) ||
graph.getLocalVariables().contains(inputsVectorVar)
)
throw new OptimizationException("The usage of 'inputsVector' as a variable is not allowed with using the GAPP optimization!\nPlease rename the 'inputsVector' variable definition and usages!", graph);
boolean scalarFunctions = plugin.isUseScalarFunctions();
Plugin plugin = new Plugin();
plugin.setInvertTransformation(true);
plugin.setScalarFunctions(scalarFunctions);
plugin.setOptInserting(graph.globalSettings.isOptMaxima());
plugin.setMaximaExpand(graph.globalSettings.isOptMaxima());
CFGImporterFacade facade = new CFGImporterFacade(plugin);
facade.importGraph(graph);
//Transform divisions with constants in multiplications
ConstantDivisionTransformer.transform(graph);
GAPP gappStart = new GAPP();
HashSet<String> variables = getAllVariableNames(graph);
assignInputVariables(graph, gappStart);
// import now the graph in GAPP
GAPPDecorator vCFG = new GAPPDecorator(gappStart, variables, facade.getUsedAlgebra().getBladeCount(), scalarFunctions, facade.getUsedAlgebra().getAlgebra());
graph.accept(vCFG);
// perform further optimizations
GAPPFurtherOptimizationsFacade furtherOpt = new GAPPFurtherOptimizationsFacade();
furtherOpt.doFurtherGAPPOptimizations(graph);
//System.out.println("Memory usage of "+graph.getSource().getName());
//MemoryUsage.printMemoryUsage(graph);
return graph;
}
/**
* Adds instructions to a GAPP instance which assigns all InputVariables to a GAPPMultivector
* @param graph The ControlFlowGraph
* @param gappStart The GAPP instance
*/
private void assignInputVariables(ControlFlowGraph graph, GAPP gappStart) {
if (graph.getInputVariables().isEmpty()) return;
LinkedList<Variable> toDo = new LinkedList<Variable>(graph.getInputVariables());
//Sort variable names in for putting in inputsVector for better readability
Collections.sort(toDo, new Comparator<Variable>() {
@Override
public int compare(Variable o1, Variable o2) {
return o1.getName().compareTo(o2.getName());
}
});
HashMap<Variable, MultivectorComponent> map = new HashMap<Variable, MultivectorComponent>();
GAPPVector inputsMv = new GAPPVector("inputsVector");
Variableset varSet = new Variableset();
int slotNo = 0;
for (Variable var : toDo) {
varSet.add(new GAPPScalarVariable(var.getName()));
map.put(var, new MultivectorComponent(inputsMv.getName(), slotNo));
slotNo++;
}
gappStart.addInstruction(new GAPPAssignInputsVector(varSet));
while (!toDo.isEmpty()) {
Variable curVar = toDo.removeFirst();
ReplaceVisitor replaceVisitor = new ReplaceVisitor(curVar, map.get(curVar));
graph.accept(replaceVisitor);
}
}
/**
* Returns a set of all Variable names in a ControlFlowGraph
* @param graph The ControlFlowGraph
* @return The set of all Variable names
*/
private HashSet<String> getAllVariableNames(ControlFlowGraph graph) {
final HashSet<String> result = new HashSet<String>();
ControlFlowVisitor visitor = new EmptyControlFlowVisitor() {
private ExpressionVisitor visitorExp = new EmptyExpressionVisitor() {
@Override
public void visit(MultivectorComponent node) {
result.add(node.getName());
super.visit(node);
}
@Override
public void visit(Variable node) {
result.add(node.getName());
super.visit(node);
}
};
@Override
public void visit(AssignmentNode node) {
node.getVariable().accept(visitorExp);
node.getValue().accept(visitorExp);
super.visit(node);
}
@Override
public void visit(StoreResultNode node) {
node.getValue().accept(visitorExp);
super.visit(node);
}
};
graph.accept(visitor);
return result;
}
}