From fa0e8849313366c951d8c5bba96ac17fa611fae0 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 29 Jan 2017 23:33:51 +0300 Subject: [PATCH] Optimize if statement to ternary conditional expression --- .../org/teavm/ast/optimization/Optimizer.java | 14 +---- .../ast/optimization/OptimizingVisitor.java | 62 ++++++++++++++++++- .../rendering/StatementRenderer.java | 2 +- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/teavm/ast/optimization/Optimizer.java b/core/src/main/java/org/teavm/ast/optimization/Optimizer.java index 466898afc..6be5e4213 100644 --- a/core/src/main/java/org/teavm/ast/optimization/Optimizer.java +++ b/core/src/main/java/org/teavm/ast/optimization/Optimizer.java @@ -35,14 +35,9 @@ public class Optimizer { ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); stats.analyze(program); boolean[] preservedVars = new boolean[stats.writes.length]; - for (int i = 0; i < preservedVars.length; ++i) { - if (stats.writes[i] != 1) { - preservedVars[i] = true; - } - } BreakEliminator breakEliminator = new BreakEliminator(); breakEliminator.eliminate(method.getBody()); - OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.reads); + OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads); method.getBody().acceptVisitor(optimizer); method.setBody(optimizer.resultStmt); int paramCount = method.getReference().parameterCount(); @@ -70,17 +65,12 @@ public class Optimizer { boolean[] preservedVars = new boolean[method.getVariables().size()]; ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); stats.analyze(splitter.getProgram(i)); - for (int j = 0; j < stats.writes.length; ++j) { - if (stats.writes[j] != 1 && stats.reads[j] > 0) { - preservedVars[j] = true; - } - } AsyncMethodPart part = method.getBody().get(i); BreakEliminator breakEliminator = new BreakEliminator(); breakEliminator.eliminate(part.getStatement()); findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars); - OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.reads); + OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads); part.getStatement().acceptVisitor(optimizer); part.setStatement(optimizer.resultStmt); } diff --git a/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java b/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java index 43ffbe3db..8dc0deb64 100644 --- a/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java +++ b/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java @@ -63,12 +63,14 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { private Expr resultExpr; Statement resultStmt; private final boolean[] preservedVars; + private final int[] writeFrequencies; private final int[] readFrequencies; private List resultSequence; - OptimizingVisitor(boolean[] preservedVars, int[] readFreqencies) { + OptimizingVisitor(boolean[] preservedVars, int[] writeFrequencies, int[] readFrequencies) { this.preservedVars = preservedVars; - this.readFrequencies = readFreqencies; + this.writeFrequencies = writeFrequencies; + this.readFrequencies = readFrequencies; } private static boolean isZero(Expr expr) { @@ -196,6 +198,9 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { public void visit(VariableExpr expr) { int index = expr.getIndex(); resultExpr = expr; + if (writeFrequencies[index] != 1) { + return; + } if (readFrequencies[index] != 1 || preservedVars[index]) { return; } @@ -569,7 +574,58 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { statement.getConsequent().addAll(consequent); statement.getAlternative().clear(); statement.getAlternative().addAll(alternative); - resultStmt = statement; + + Statement asConditional = tryConvertToConditionalExpression(statement); + if (asConditional != null) { + asConditional.acceptVisitor(this); + } else { + resultStmt = statement; + } + } + + private Statement tryConvertToConditionalExpression(ConditionalStatement statement) { + if (statement.getConsequent().size() != 1 || statement.getAlternative().size() != 1) { + return null; + } + + Statement first = statement.getConsequent().get(0); + Statement second = statement.getAlternative().get(0); + if (!(first instanceof AssignmentStatement) || !(second instanceof AssignmentStatement)) { + return null; + } + + AssignmentStatement firstAssignment = (AssignmentStatement) first; + AssignmentStatement secondAssignment = (AssignmentStatement) second; + if (firstAssignment.getLeftValue() == null || secondAssignment.getRightValue() == null) { + return null; + } + if (firstAssignment.isAsync() || secondAssignment.isAsync()) { + return null; + } + + if (!(firstAssignment.getLeftValue() instanceof VariableExpr) + || !(secondAssignment.getLeftValue() instanceof VariableExpr)) { + return null; + } + VariableExpr firstLhs = (VariableExpr) firstAssignment.getLeftValue(); + VariableExpr secondLhs = (VariableExpr) secondAssignment.getLeftValue(); + if (firstLhs.getIndex() == secondLhs.getIndex()) { + ConditionalExpr conditionalExpr = new ConditionalExpr(); + conditionalExpr.setCondition(statement.getCondition()); + conditionalExpr.setConsequent(firstAssignment.getRightValue()); + conditionalExpr.setAlternative(secondAssignment.getRightValue()); + conditionalExpr.setLocation(statement.getCondition().getLocation()); + AssignmentStatement assignment = new AssignmentStatement(); + assignment.setLocation(conditionalExpr.getLocation()); + VariableExpr lhs = new VariableExpr(); + lhs.setIndex(firstLhs.getIndex()); + assignment.setLeftValue(lhs); + assignment.setRightValue(conditionalExpr); + writeFrequencies[lhs.getIndex()]--; + return assignment; + } + + return null; } @Override diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java index bc7fbf1c3..8b556b302 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java @@ -936,7 +936,7 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor { expr.getAlternative().acceptVisitor(this); if (outerPrecedence.ordinal() > Precedence.CONDITIONAL.ordinal()) { - writer.append('('); + writer.append(')'); } if (expr.getLocation() != null) {