package de.gaalop.tba.cfgImport.optimization;
import de.gaalop.api.dfg.DFGNodeType;
import de.gaalop.api.dfg.DFGNodeTypeGetter;
import de.gaalop.cfg.AssignmentNode;
import de.gaalop.cfg.ColorNode;
import de.gaalop.cfg.EmptyControlFlowVisitor;
import de.gaalop.cfg.ExpressionStatement;
import de.gaalop.cfg.StoreResultNode;
import de.gaalop.dfg.Expression;
import de.gaalop.dfg.FloatConstant;
import java.util.HashMap;
/**
* This class tries to optimize a ControlFlowGraph
* using the Constant Propagation and Constant Folding
* @author Christian Steinmetz
*/
public class ConstantPropagation extends EmptyControlFlowVisitor {
private ConstantFolding constantFolding = new ConstantFolding();
private HashMap<VariableComponent, FloatConstant> mapConstants = new HashMap<VariableComponent, FloatConstant>();
private DFGVisitorUsedVariables dfgVisitorUsedVariables = new DFGVisitorUsedVariables();
private boolean graphModified = false;
public boolean isGraphModified() {
return graphModified;
}
private void setGraphModified() {
graphModified = true;
}
/**
* Performs constant propagtion on an expression and returns the result expression
* @param expression the expression for constant propagtion
* @return the result expression, where constant variables are constant
*/
private Expression performConstantPropagationOnExpression(Expression expression) {
dfgVisitorUsedVariables.getVariables().clear();
expression.accept(dfgVisitorUsedVariables);
for (VariableComponent varComp : dfgVisitorUsedVariables.getVariables()) {
if (mapConstants.containsKey(varComp)) {
// replace variable with constant
if (expression == varComp.getReferredExpression()) {
expression = mapConstants.get(varComp);
} else {
expression.replaceExpression(varComp.getReferredExpression(), mapConstants.get(varComp));
}
setGraphModified();
}
}
// do a constant folding on the value
expression.accept(constantFolding);
if (constantFolding.isGraphModified()) {
setGraphModified();
}
return constantFolding.getResultExpr();
}
@Override
public void visit(AssignmentNode node) {
node.setValue(performConstantPropagationOnExpression(node.getValue()));
// get variable component of target
dfgVisitorUsedVariables.getVariables().clear();
node.getVariable().accept(dfgVisitorUsedVariables);
VariableComponent target = dfgVisitorUsedVariables.getVariables().getFirst();
// remove variable component from mapConstants, because of re-assignment
mapConstants.remove(target);
if (isFloatConstant(node.getValue())) {
mapConstants.put(target, (FloatConstant) node.getValue());
}
super.visit(node);
}
@Override
public void visit(ColorNode node) {
node.setR(performConstantPropagationOnExpression(node.getR()));
node.setG(performConstantPropagationOnExpression(node.getG()));
node.setB(performConstantPropagationOnExpression(node.getB()));
node.setAlpha(performConstantPropagationOnExpression(node.getAlpha()));
super.visit(node);
}
@Override
public void visit(ExpressionStatement node) {
node.setExpression(performConstantPropagationOnExpression(node.getExpression()));
super.visit(node);
}
@Override
public void visit(StoreResultNode node) {
// Do nothing, because node.getValue is of type Variable, not Expression
super.visit(node);
}
/**
* Determines if a expression is a FloatConstant
* @param expression The expression to be checked
* @return <value>true</value> if the expression is a FloatConstant, <value>false</value> otherwise
*/
private boolean isFloatConstant(Expression expression) {
return DFGNodeTypeGetter.getTypeOfDFGNode(expression) == DFGNodeType.FloatConstant;
}
}