Refactor optimization API

This commit is contained in:
Alexey Andreev 2016-11-24 22:41:56 +03:00 committed by Alexey Andreev
parent b7d760188e
commit 0b4629d959
15 changed files with 85 additions and 25 deletions

View File

@ -37,7 +37,7 @@ public class PreOptimizingClassHolderSource implements ClassHolderSource {
return null; return null;
} }
for (MethodHolder method : cls.getMethods()) { for (MethodHolder method : cls.getMethods()) {
new GlobalValueNumbering(true).optimize(method, method.getProgram()); new GlobalValueNumbering(true).optimize(method.getProgram());
new UnusedVariableElimination().optimize(method, method.getProgram()); new UnusedVariableElimination().optimize(method, method.getProgram());
} }
cache.put(name, cls); cache.put(name, cls);

View File

@ -24,7 +24,7 @@ import org.teavm.model.util.DefinitionExtractor;
public class ArrayUnwrapMotion implements MethodOptimization { public class ArrayUnwrapMotion implements MethodOptimization {
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
for (int i = 0; i < program.basicBlockCount(); ++i) { for (int i = 0; i < program.basicBlockCount(); ++i) {
optimize(program.basicBlockAt(i)); optimize(program.basicBlockAt(i));
} }

View File

@ -25,7 +25,6 @@ import org.teavm.common.Graph;
import org.teavm.common.GraphUtils; import org.teavm.common.GraphUtils;
import org.teavm.model.BasicBlock; import org.teavm.model.BasicBlock;
import org.teavm.model.Instruction; import org.teavm.model.Instruction;
import org.teavm.model.MethodReader;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.instructions.EmptyInstruction; import org.teavm.model.instructions.EmptyInstruction;
import org.teavm.model.instructions.InitClassInstruction; import org.teavm.model.instructions.InitClassInstruction;
@ -34,13 +33,13 @@ import org.teavm.model.util.ProgramUtils;
public class ClassInitElimination implements MethodOptimization { public class ClassInitElimination implements MethodOptimization {
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
Graph cfg = ProgramUtils.buildControlFlowGraph(program); Graph cfg = ProgramUtils.buildControlFlowGraph(program);
DominatorTree dom = GraphUtils.buildDominatorTree(cfg); DominatorTree dom = GraphUtils.buildDominatorTree(cfg);
Graph domGraph = GraphUtils.buildDominatorGraph(dom, program.basicBlockCount()); Graph domGraph = GraphUtils.buildDominatorGraph(dom, program.basicBlockCount());
Step start = new Step(0); Step start = new Step(0);
start.initializedClasses.add(method.getOwnerName()); start.initializedClasses.add(context.getMethod().getOwnerName());
Deque<Step> stack = new ArrayDeque<>(); Deque<Step> stack = new ArrayDeque<>();
stack.push(start); stack.push(start);

View File

@ -17,7 +17,6 @@ package org.teavm.model.optimization;
import org.teavm.model.BasicBlock; import org.teavm.model.BasicBlock;
import org.teavm.model.Instruction; import org.teavm.model.Instruction;
import org.teavm.model.MethodReader;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.instructions.BinaryBranchingCondition; import org.teavm.model.instructions.BinaryBranchingCondition;
import org.teavm.model.instructions.BinaryBranchingInstruction; import org.teavm.model.instructions.BinaryBranchingInstruction;
@ -33,7 +32,7 @@ public class ConstantConditionElimination implements MethodOptimization {
private boolean[] nullConstants; private boolean[] nullConstants;
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
constants = new int[program.variableCount()]; constants = new int[program.variableCount()];
constantDefined = new boolean[program.variableCount()]; constantDefined = new boolean[program.variableCount()];
nullConstants = new boolean[program.variableCount()]; nullConstants = new boolean[program.variableCount()];

View File

@ -16,14 +16,13 @@
package org.teavm.model.optimization; package org.teavm.model.optimization;
import org.teavm.model.BasicBlock; import org.teavm.model.BasicBlock;
import org.teavm.model.MethodReader;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.instructions.JumpInstruction; import org.teavm.model.instructions.JumpInstruction;
import org.teavm.model.util.BasicBlockMapper; import org.teavm.model.util.BasicBlockMapper;
public class EmptyBlockElimination implements MethodOptimization { public class EmptyBlockElimination implements MethodOptimization {
@Override @Override
public boolean optimize(MethodReader method, final Program program) { public boolean optimize(MethodOptimizationContext context, final Program program) {
boolean affected = true; boolean affected = true;
final int[] blockMapping = new int[program.basicBlockCount()]; final int[] blockMapping = new int[program.basicBlockCount()];
for (int i = 0; i < blockMapping.length; ++i) { for (int i = 0; i < blockMapping.length; ++i) {

View File

@ -46,7 +46,11 @@ public class GlobalValueNumbering implements MethodOptimization {
} }
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
return optimize(program);
}
public boolean optimize(Program program) {
boolean affected = false; boolean affected = false;
this.program = program; this.program = program;
knownValues.clear(); knownValues.clear();

View File

@ -30,7 +30,7 @@ public class LoopInvariantMotion implements MethodOptimization {
private Program program; private Program program;
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
boolean affected = false; boolean affected = false;
this.program = program; this.program = program;
graph = new LoopGraph(ProgramUtils.buildControlFlowGraph(program)); graph = new LoopGraph(ProgramUtils.buildControlFlowGraph(program));
@ -42,7 +42,7 @@ public class LoopInvariantMotion implements MethodOptimization {
int[] defLocation = new int[program.variableCount()]; int[] defLocation = new int[program.variableCount()];
Arrays.fill(defLocation, -1); Arrays.fill(defLocation, -1);
Instruction[] constantInstructions = new Instruction[program.variableCount()]; Instruction[] constantInstructions = new Instruction[program.variableCount()];
for (int i = 0; i <= method.parameterCount(); ++i) { for (int i = 0; i <= context.getMethod().parameterCount(); ++i) {
defLocation[i] = 0; defLocation[i] = 0;
} }
for (int i = 0; i < domGraph.size(); ++i) { for (int i = 0; i < domGraph.size(); ++i) {

View File

@ -20,7 +20,8 @@ import org.teavm.model.Program;
public class LoopInversion implements MethodOptimization { public class LoopInversion implements MethodOptimization {
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
MethodReader method = context.getMethod();
return new LoopInversionImpl(method, program, method.parameterCount() + 1).apply(); return new LoopInversionImpl(method, program, method.parameterCount() + 1).apply();
} }
} }

View File

@ -152,10 +152,10 @@ class LoopInversionImpl {
} }
private LoopWithExits getLoopWithExits(Map<Loop, LoopWithExits> cache, Loop loop) { private LoopWithExits getLoopWithExits(Map<Loop, LoopWithExits> cache, Loop loop) {
return cache.computeIfAbsent(loop, k -> return cache.computeIfAbsent(loop, k -> {
new LoopWithExits(loop.getHead(), loop.getParent() != null LoopWithExits parent = loop.getParent() != null ? getLoopWithExits(cache, loop.getParent()) : null;
? getLoopWithExits(cache, loop.getParent()) return new LoopWithExits(loop.getHead(), parent);
: null)); });
} }
private void sortLoops(LoopWithExits loop, Set<LoopWithExits> visited, List<LoopWithExits> target) { private void sortLoops(LoopWithExits loop, Set<LoopWithExits> visited, List<LoopWithExits> target) {

View File

@ -15,9 +15,8 @@
*/ */
package org.teavm.model.optimization; package org.teavm.model.optimization;
import org.teavm.model.MethodReader;
import org.teavm.model.Program; import org.teavm.model.Program;
public interface MethodOptimization { public interface MethodOptimization {
boolean optimize(MethodReader method, Program program); boolean optimize(MethodOptimizationContext context, Program program);
} }

View File

@ -0,0 +1,28 @@
/*
* Copyright 2016 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.model.optimization;
import org.teavm.dependency.DependencyInfo;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.MethodReader;
public interface MethodOptimizationContext {
MethodReader getMethod();
DependencyInfo getDependencyInfo();
ClassReaderSource getClassSource();
}

View File

@ -22,7 +22,6 @@ import org.teavm.common.Graph;
import org.teavm.model.BasicBlock; import org.teavm.model.BasicBlock;
import org.teavm.model.Incoming; import org.teavm.model.Incoming;
import org.teavm.model.Instruction; import org.teavm.model.Instruction;
import org.teavm.model.MethodReader;
import org.teavm.model.Phi; import org.teavm.model.Phi;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.TryCatchBlock; import org.teavm.model.TryCatchBlock;
@ -33,7 +32,7 @@ import org.teavm.model.util.ProgramUtils;
public class RedundantJumpElimination implements MethodOptimization { public class RedundantJumpElimination implements MethodOptimization {
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
Graph cfg = ProgramUtils.buildControlFlowGraph(program); Graph cfg = ProgramUtils.buildControlFlowGraph(program);
int[] incomingCount = new int[cfg.size()]; int[] incomingCount = new int[cfg.size()];
Arrays.setAll(incomingCount, cfg::incomingEdgesCount); Arrays.setAll(incomingCount, cfg::incomingEdgesCount);

View File

@ -15,12 +15,11 @@
*/ */
package org.teavm.model.optimization; package org.teavm.model.optimization;
import org.teavm.model.MethodReader;
import org.teavm.model.Program; import org.teavm.model.Program;
public class UnreachableBasicBlockElimination implements MethodOptimization { public class UnreachableBasicBlockElimination implements MethodOptimization {
@Override @Override
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodOptimizationContext context, Program program) {
new UnreachableBasicBlockEliminator().optimize(program); new UnreachableBasicBlockEliminator().optimize(program);
return false; return false;
} }

View File

@ -21,6 +21,10 @@ import org.teavm.model.instructions.*;
public class UnusedVariableElimination implements MethodOptimization { public class UnusedVariableElimination implements MethodOptimization {
@Override @Override
public boolean optimize(MethodOptimizationContext context, Program program) {
return optimize(context.getMethod(), program);
}
public boolean optimize(MethodReader method, Program program) { public boolean optimize(MethodReader method, Program program) {
if (method.getProgram() == null) { if (method.getProgram() == null) {
return false; return false;

View File

@ -45,6 +45,7 @@ import org.teavm.model.ClassReaderSource;
import org.teavm.model.ListableClassHolderSource; import org.teavm.model.ListableClassHolderSource;
import org.teavm.model.ListableClassReaderSource; import org.teavm.model.ListableClassReaderSource;
import org.teavm.model.MethodHolder; import org.teavm.model.MethodHolder;
import org.teavm.model.MethodReader;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.MutableClassHolderSource; import org.teavm.model.MutableClassHolderSource;
import org.teavm.model.Program; import org.teavm.model.Program;
@ -58,6 +59,7 @@ import org.teavm.model.optimization.Inlining;
import org.teavm.model.optimization.LoopInvariantMotion; import org.teavm.model.optimization.LoopInvariantMotion;
import org.teavm.model.optimization.LoopInversion; import org.teavm.model.optimization.LoopInversion;
import org.teavm.model.optimization.MethodOptimization; import org.teavm.model.optimization.MethodOptimization;
import org.teavm.model.optimization.MethodOptimizationContext;
import org.teavm.model.optimization.RedundantJumpElimination; import org.teavm.model.optimization.RedundantJumpElimination;
import org.teavm.model.optimization.UnreachableBasicBlockElimination; import org.teavm.model.optimization.UnreachableBasicBlockElimination;
import org.teavm.model.optimization.UnusedVariableElimination; import org.teavm.model.optimization.UnusedVariableElimination;
@ -443,8 +445,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
ClassHolder cls = classes.get(className); ClassHolder cls = classes.get(className);
for (MethodHolder method : cls.getMethods()) { for (MethodHolder method : cls.getMethods()) {
if (method.getProgram() != null) { if (method.getProgram() != null) {
MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method, classes);
inlining.apply(method.getProgram(), classes); inlining.apply(method.getProgram(), classes);
new UnusedVariableElimination().optimize(method, method.getProgram()); new UnusedVariableElimination().optimize(context, method.getProgram());
} }
} }
if (wasCancelled()) { if (wasCancelled()) {
@ -473,6 +476,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
boolean noCache = method.getAnnotations().get(NoCache.class.getName()) != null; boolean noCache = method.getAnnotations().get(NoCache.class.getName()) != null;
Program optimizedProgram = incremental && !noCache && programCache != null Program optimizedProgram = incremental && !noCache && programCache != null
? programCache.get(method.getReference()) : null; ? programCache.get(method.getReference()) : null;
MethodOptimizationContextImpl context = new MethodOptimizationContextImpl(method, classSource);
if (optimizedProgram == null) { if (optimizedProgram == null) {
optimizedProgram = ProgramUtils.copy(method.getProgram()); optimizedProgram = ProgramUtils.copy(method.getProgram());
if (optimizedProgram.basicBlockCount() > 0) { if (optimizedProgram.basicBlockCount() > 0) {
@ -481,7 +485,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
changed = false; changed = false;
for (MethodOptimization optimization : getOptimizations()) { for (MethodOptimization optimization : getOptimizations()) {
try { try {
changed |= optimization.optimize(method, optimizedProgram); changed |= optimization.optimize(context, optimizedProgram);
} catch (Exception | AssertionError e) { } catch (Exception | AssertionError e) {
ListingBuilder listingBuilder = new ListingBuilder(); ListingBuilder listingBuilder = new ListingBuilder();
String listing = listingBuilder.buildListing(optimizedProgram, ""); String listing = listingBuilder.buildListing(optimizedProgram, "");
@ -505,6 +509,31 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
method.setProgram(optimizedProgram); method.setProgram(optimizedProgram);
} }
private class MethodOptimizationContextImpl implements MethodOptimizationContext {
private MethodReader method;
private ClassReaderSource classSource;
public MethodOptimizationContextImpl(MethodReader method, ClassReaderSource classSource) {
this.method = method;
this.classSource = classSource;
}
@Override
public MethodReader getMethod() {
return method;
}
@Override
public DependencyInfo getDependencyInfo() {
return dependencyChecker;
}
@Override
public ClassReaderSource getClassSource() {
return classSource;
}
}
private List<MethodOptimization> getOptimizations() { private List<MethodOptimization> getOptimizations() {
List<MethodOptimization> optimizations = new ArrayList<>(); List<MethodOptimization> optimizations = new ArrayList<>();
optimizations.add(new RedundantJumpElimination()); optimizations.add(new RedundantJumpElimination());