Добавлен оптимизация: объединение инструкций

This commit is contained in:
Victor 2016-06-26 16:32:48 +03:00
parent 1b9c5187f6
commit 692370eb4b
3 changed files with 121 additions and 2 deletions

View File

@ -7,6 +7,7 @@ import com.annimon.ownlang.parser.optimization.ConstantFolding;
import com.annimon.ownlang.parser.optimization.ConstantPropagation;
import com.annimon.ownlang.parser.optimization.DeadCodeElimination;
import com.annimon.ownlang.parser.optimization.ExpressionSimplification;
import com.annimon.ownlang.parser.optimization.InstructionCombining;
import com.annimon.ownlang.parser.optimization.Optimizable;
import com.annimon.ownlang.parser.optimization.SummaryOptimization;
@ -19,11 +20,12 @@ public final class Optimizer {
new ConstantFolding(),
new ConstantPropagation(),
new DeadCodeElimination(),
new ExpressionSimplification()
new ExpressionSimplification(),
new InstructionCombining()
});
Node result = statement;
if (true || level >= 9) {
if (level >= 9) {
int iteration = 0, lastModifications = 0;
do {
lastModifications = optimization.optimizationsCount();

View File

@ -0,0 +1,110 @@
package com.annimon.ownlang.parser.optimization;
import com.annimon.ownlang.parser.ast.BlockStatement;
import com.annimon.ownlang.parser.ast.Expression;
import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.PrintStatement;
import com.annimon.ownlang.parser.ast.PrintlnStatement;
import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.ast.ValueExpression;
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isConstantValue;
/**
* Performs instruction combining.
*/
public class InstructionCombining extends OptimizationVisitor<Void> implements Optimizable {
private int printCombinedCount;
@Override
public Node optimize(Node node) {
return node.accept(this, null);
}
@Override
public int optimizationsCount() {
return printCombinedCount;
}
@Override
public String summaryInfo() {
if (optimizationsCount() == 0) return "";
final StringBuilder sb = new StringBuilder();
if (printCombinedCount > 0) {
sb.append("\nPrint statement combined: ").append(printCombinedCount);
}
return sb.toString();
}
@Override
public Node visit(BlockStatement s, Void t) {
final int size = s.statements.size();
if (size <= 1) {
return super.visit(s, t);
}
boolean changed = false;
final BlockStatement result = new BlockStatement();
int i;
for (i = 1; i < size; i++) {
Statement s1 = s.statements.get(i - 1);
Statement s2 = s.statements.get(i);
Node n1 = s1.accept(this, t);
Node n2 = s2.accept(this, t);
if (n1 != s1 || n2 != s2) {
changed = true;
}
final Node combined = tryCombine(n1, n2);
if (combined == null) {
result.add((Statement) n1);
} else {
changed = true;
result.add(consumeStatement(combined));
i++;
}
}
if (i == size) {
// Last node
Statement s2 = s.statements.get(size - 1);
Node n2 = s2.accept(this, t);
if (n2 != s2) {
changed = true;
}
result.add((Statement) n2);
}
if (changed) {
return result;
}
return super.visit(s, t);
}
private Node tryCombine(Node n1, Node n2) {
final int n1Type;
if (n1 instanceof PrintStatement) n1Type = 1;
else if (n1 instanceof PrintlnStatement) n1Type = 2;
else n1Type = 0;
final int n2Type;
if (n2 instanceof PrintStatement) n2Type = 1;
else if (n2 instanceof PrintlnStatement) n2Type = 2;
else n2Type = 0;
if (n1Type != 0 && n2Type != 0) {
final Expression e1 = (n1Type == 1)
? ((PrintStatement) n1).expression
: ((PrintlnStatement) n1).expression;
final Expression e2 = (n2Type == 1)
? ((PrintStatement) n2).expression
: ((PrintlnStatement) n2).expression;
if (isConstantValue(e1) && isConstantValue(e2)) {
String s1 = e1.eval().asString();
if (n1Type == 2) s1 += System.lineSeparator();
String s2 = e2.eval().asString();
if (n2Type == 2) s2 += System.lineSeparator();
printCombinedCount++;
return new PrintStatement(new ValueExpression(s1 + s2));
}
}
return null;
}
}

View File

@ -56,6 +56,13 @@ public final class VisitorUtils {
return value.asInt() == valueToCheck;
}
public static boolean isConstantValue(Node node) {
if (!isValue(node)) return false;
final int type = ((ValueExpression) node).value.type();
return ( (type == Types.NUMBER) || (type == Types.STRING) );
}
public static boolean isSameVariables(Node n1, Node n2) {
if (isVariable(n1) && isVariable(n2)) {
final VariableExpression v1 = (VariableExpression) n1;