From 3d691672807bad2fb6340e685f2aec80ed3ef9d4 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sat, 14 May 2016 23:36:19 +0300 Subject: [PATCH] Refactor block mappers. Remove phi placement from loop inversion, since it's easier to make SSATransformer incremental and call it after each application of loop inversion --- .idea/scala_compiler.xml | 6 + .../teavm/model/util/BasicBlockMapper.java | 14 +- .../model/util/InstructionVariableMapper.java | 12 ++ .../util/ProgramNodeSplittingBackend.java | 22 +-- .../teavm/model/util/RegisterAllocator.java | 11 +- .../optimization/EmptyBlockElimination.java | 6 +- .../optimization/LoopInvariantMotion.java | 10 +- .../teavm/optimization/LoopInversionImpl.java | 183 +----------------- core/src/main/java/org/teavm/vm/TeaVM.java | 2 +- 9 files changed, 47 insertions(+), 219 deletions(-) create mode 100644 .idea/scala_compiler.xml diff --git a/.idea/scala_compiler.xml b/.idea/scala_compiler.xml new file mode 100644 index 000000000..c78926c8c --- /dev/null +++ b/.idea/scala_compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java b/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java index 19bbce401..a422221e8 100644 --- a/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java +++ b/core/src/main/java/org/teavm/model/util/BasicBlockMapper.java @@ -15,6 +15,7 @@ */ package org.teavm.model.util; +import java.util.function.IntUnaryOperator; import org.teavm.model.*; import org.teavm.model.instructions.*; @@ -22,8 +23,17 @@ import org.teavm.model.instructions.*; * * @author Alexey Andreev */ -public abstract class BasicBlockMapper implements InstructionVisitor { - protected abstract BasicBlock map(BasicBlock block); +public class BasicBlockMapper implements InstructionVisitor { + private IntUnaryOperator mapFunction; + + public BasicBlockMapper(IntUnaryOperator mapFunction) { + this.mapFunction = mapFunction; + } + + private BasicBlock map(BasicBlock block) { + Program program = block.getProgram(); + return program.basicBlockAt(mapFunction.applyAsInt(block.getIndex())); + } public void transform(Program program) { for (int i = 0; i < program.basicBlockCount(); ++i) { diff --git a/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java b/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java index 3da89e137..fa6bbd64d 100644 --- a/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java +++ b/core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java @@ -33,15 +33,27 @@ public class InstructionVariableMapper implements InstructionVisitor { } public void apply(BasicBlock block) { + applyToInstructions(block); + applyToPhis(block); + applyToTryCatchBlocks(block); + } + + public void applyToInstructions(BasicBlock block) { for (Instruction insn : block.getInstructions()) { insn.acceptVisitor(this); } + } + + public void applyToPhis(BasicBlock block) { for (Phi phi : block.getPhis()) { phi.setReceiver(map(phi.getReceiver())); for (Incoming incoming : phi.getIncomings()) { incoming.setValue(map(incoming.getValue())); } } + } + + public void applyToTryCatchBlocks(BasicBlock block) { for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { if (tryCatch.getExceptionVariable() != null) { tryCatch.setExceptionVariable(map(tryCatch.getExceptionVariable())); diff --git a/core/src/main/java/org/teavm/model/util/ProgramNodeSplittingBackend.java b/core/src/main/java/org/teavm/model/util/ProgramNodeSplittingBackend.java index 4a2da749e..7369f7c38 100644 --- a/core/src/main/java/org/teavm/model/util/ProgramNodeSplittingBackend.java +++ b/core/src/main/java/org/teavm/model/util/ProgramNodeSplittingBackend.java @@ -45,7 +45,10 @@ public class ProgramNodeSplittingBackend implements GraphSplittingBackend { copies[i] = blockCopy.getIndex(); map.put(nodes[i], copies[i] + 1); } - CopyBlockMapper copyBlockMapper = new CopyBlockMapper(map); + BasicBlockMapper copyBlockMapper = new BasicBlockMapper(block -> { + int mappedIndex = map.get(block); + return mappedIndex == 0 ? block : mappedIndex - 1; + }); for (int i = 0; i < copies.length; ++i) { copyBlockMapper.transform(program.basicBlockAt(copies[i])); } @@ -54,21 +57,4 @@ public class ProgramNodeSplittingBackend implements GraphSplittingBackend { } return copies; } - - private static class CopyBlockMapper extends BasicBlockMapper { - private IntIntMap map; - - public CopyBlockMapper(IntIntMap map) { - this.map = map; - } - - @Override - protected BasicBlock map(BasicBlock block) { - int mappedIndex = map.get(block.getIndex()); - if (mappedIndex == 0) { - return block; - } - return block.getProgram().basicBlockAt(mappedIndex - 1); - } - } } diff --git a/core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/core/src/main/java/org/teavm/model/util/RegisterAllocator.java index 2b407d02e..4f41d2b12 100644 --- a/core/src/main/java/org/teavm/model/util/RegisterAllocator.java +++ b/core/src/main/java/org/teavm/model/util/RegisterAllocator.java @@ -136,15 +136,8 @@ public class RegisterAllocator { JumpInstruction jumpInstruction = new JumpInstruction(); jumpInstruction.setTarget(phi.getBasicBlock()); copyBlock.getInstructions().add(jumpInstruction); - incoming.getSource().getLastInstruction().acceptVisitor(new BasicBlockMapper() { - @Override protected BasicBlock map(BasicBlock block) { - if (block == phi.getBasicBlock()) { - return copyBlock; - } else { - return block; - } - } - }); + incoming.getSource().getLastInstruction().acceptVisitor(new BasicBlockMapper(block -> + block == phi.getBasicBlock().getIndex() ? copyBlock.getIndex() : block)); blockMap.put(source, copyBlock); incoming.setSource(copyBlock); source = copyBlock; diff --git a/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java b/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java index 49ade6611..27dd8ff2b 100644 --- a/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java +++ b/core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java @@ -44,11 +44,7 @@ public class EmptyBlockElimination implements MethodOptimization { } lastNonEmpty = blockMapping[i]; } - new BasicBlockMapper() { - @Override protected BasicBlock map(BasicBlock block) { - return program.basicBlockAt(blockMapping[block.getIndex()]); - } - }.transform(program); + new BasicBlockMapper(block -> blockMapping[block]).transform(program); for (int i = 0; i < program.basicBlockCount(); ++i) { if (blockMapping[i] != i) { program.deleteBasicBlock(i); diff --git a/core/src/main/java/org/teavm/optimization/LoopInvariantMotion.java b/core/src/main/java/org/teavm/optimization/LoopInvariantMotion.java index bf38d7890..9032a237f 100644 --- a/core/src/main/java/org/teavm/optimization/LoopInvariantMotion.java +++ b/core/src/main/java/org/teavm/optimization/LoopInvariantMotion.java @@ -195,14 +195,8 @@ public class LoopInvariantMotion implements MethodOptimization { for (int predIndex : graph.incomingEdges(headerIndex)) { if (!dom.dominates(headerIndex, predIndex)) { BasicBlock pred = program.basicBlockAt(predIndex); - pred.getLastInstruction().acceptVisitor(new BasicBlockMapper() { - @Override protected BasicBlock map(BasicBlock block) { - if (block == header) { - block = preheader; - } - return block; - } - }); + pred.getLastInstruction().acceptVisitor(new BasicBlockMapper( + block -> block == header.getIndex() ? preheader.getIndex() : block)); } } return preheader.getIndex(); diff --git a/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java b/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java index 8e76b8588..c0f2e2da6 100644 --- a/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java +++ b/core/src/main/java/org/teavm/optimization/LoopInversionImpl.java @@ -38,11 +38,8 @@ import org.teavm.model.Instruction; import org.teavm.model.Phi; import org.teavm.model.Program; import org.teavm.model.TryCatchBlock; -import org.teavm.model.Variable; import org.teavm.model.util.BasicBlockMapper; -import org.teavm.model.util.DefinitionExtractor; import org.teavm.model.util.InstructionCopyReader; -import org.teavm.model.util.InstructionVariableMapper; import org.teavm.model.util.ProgramUtils; /** @@ -69,8 +66,8 @@ import org.teavm.model.util.ProgramUtils; * where `condition` is a part of loop that has exits and `body` has no exits. * More formally, we define *body start candidate* as a node which 1) dominates all of the "tails" (i.e. nodes * that have edges to loop header), 2) does not dominate loop exits. *Body start* is a body start candidate - * that is not dominates by some other body start candidate. If body start does not exits, loop is - * not inversible. + * that is not dominated by some other body start candidate. If body start does not exits, loop is + * not invertible. * * Therefore, *body* is a set of nodes of the loop that are dominated by body start and * all remaining nodes are *condition*. @@ -154,10 +151,7 @@ class LoopInversionImpl { int bodyStart; int copyStart; int headCopy; - final IntIntMap copiedVars = new IntIntOpenHashMap(); final IntIntMap copiedNodes = new IntIntOpenHashMap(); - final IntIntMap varDefinitionPoints = new IntIntOpenHashMap(); - final IntIntMap newHeadPhiMap = new IntIntOpenHashMap(); boolean shouldSkip; LoopWithExits(int head, LoopWithExits parent) { @@ -186,13 +180,10 @@ class LoopInversionImpl { } collectNodesToCopy(); - collectVariablesToCopy(); copyCondition(); moveBackEdges(); - putNewPhis(); removeInternalPhiInputsFromCondition(); removeExternalPhiInputsFromConditionCopy(); - adjustOutputPhis(); return true; } @@ -235,40 +226,8 @@ class LoopInversionImpl { } } - private void collectVariablesToCopy() { - DefinitionExtractor definitionExtractor = new DefinitionExtractor(); - IntSet varsToCopy = new IntOpenHashSet(); - for (int node : copiedNodes.keys().toArray()) { - BasicBlock block = program.basicBlockAt(node); - for (Instruction insn : block.getInstructions()) { - insn.acceptVisitor(definitionExtractor); - for (Variable var : definitionExtractor.getDefinedVariables()) { - varsToCopy.add(var.getIndex()); - varDefinitionPoints.put(var.getIndex(), node); - } - } - for (Phi phi : block.getPhis()) { - varsToCopy.add(phi.getReceiver().getIndex()); - varDefinitionPoints.put(phi.getReceiver().getIndex(), node); - } - } - - int[] orderedVarsToCopy = varsToCopy.toArray(); - Arrays.sort(orderedVarsToCopy); - for (int var : orderedVarsToCopy) { - copiedVars.put(var, program.createVariable().getIndex()); - } - } - private void copyCondition() { - InstructionVariableMapper variableMapper = new InstructionVariableMapper(var -> - program.variableAt(copiedVars.getOrDefault(var.getIndex(), var.getIndex()))); - BasicBlockMapper blockMapper = new BasicBlockMapper() { - @Override - protected BasicBlock map(BasicBlock block) { - return program.basicBlockAt(copiedNodes.getOrDefault(block.getIndex(), block.getIndex())); - } - }; + BasicBlockMapper blockMapper = new BasicBlockMapper(block -> copiedNodes.getOrDefault(block, block)); InstructionCopyReader copier = new InstructionCopyReader(program); for (int node : copiedNodes.keys().toArray()) { @@ -278,21 +237,18 @@ class LoopInversionImpl { for (int i = 0; i < sourceBlock.instructionCount(); ++i) { sourceBlock.readInstruction(i, copier); Instruction insn = copier.getCopy(); - insn.acceptVisitor(variableMapper); insn.acceptVisitor(blockMapper); targetBlock.getInstructions().add(insn); } for (Phi phi : sourceBlock.getPhis()) { Phi phiCopy = new Phi(); - int receiver = phi.getReceiver().getIndex(); - phiCopy.setReceiver(program.variableAt(copiedVars.getOrDefault(receiver, receiver))); + phiCopy.setReceiver(phi.getReceiver()); for (Incoming incoming : phi.getIncomings()) { Incoming incomingCopy = new Incoming(); int source = incoming.getSource().getIndex(); - int value = incoming.getValue().getIndex(); incomingCopy.setSource(program.basicBlockAt(copiedNodes.getOrDefault(source, source))); - incomingCopy.setValue(program.variableAt(copiedVars.getOrDefault(value, value))); + incomingCopy.setValue(incoming.getValue()); phiCopy.getIncomings().add(incomingCopy); } targetBlock.getPhis().add(phiCopy); @@ -300,10 +256,9 @@ class LoopInversionImpl { for (TryCatchBlock tryCatch : sourceBlock.getTryCatchBlocks()) { TryCatchBlock tryCatchCopy = new TryCatchBlock(); - int var = tryCatch.getExceptionVariable().getIndex(); int handler = tryCatch.getHandler().getIndex(); tryCatchCopy.setExceptionType(tryCatch.getExceptionType()); - tryCatchCopy.setExceptionVariable(program.variableAt(copiedVars.getOrDefault(var, var))); + tryCatchCopy.setExceptionVariable(tryCatch.getExceptionVariable()); tryCatchCopy.setHandler(program.basicBlockAt(copiedNodes.getOrDefault(handler, handler))); targetBlock.getTryCatchBlocks().add(tryCatchCopy); } @@ -314,12 +269,7 @@ class LoopInversionImpl { * Back edges from body are not back edges anymore, instead they point to a copied condition. */ private void moveBackEdges() { - BasicBlockMapper mapper = new BasicBlockMapper() { - @Override - protected BasicBlock map(BasicBlock block) { - return block.getIndex() == head ? program.basicBlockAt(headCopy) : block; - } - }; + BasicBlockMapper mapper = new BasicBlockMapper(block -> block == head ? headCopy : block); for (int node : nodes.toArray()) { BasicBlock block = program.basicBlockAt(node); @@ -359,128 +309,9 @@ class LoopInversionImpl { Incoming incoming = incomings.get(i); if (!nodesAndCopies.contains(incoming.getSource().getIndex())) { incomings.remove(i--); - } else { - int var = incoming.getValue().getIndex(); - incoming.setValue(program.variableAt(newHeadPhiMap.getOrDefault(var, var))); } } } } - - /** - * Variables defined in condition should be converted to phis in a new loop head (i.e. body start). - * Every reference to variable from old condition must be replaced by reference to corresponding phi. - */ - private void putNewPhis() { - BasicBlock head = program.basicBlockAt(bodyStart); - IntIntMap phiMap = new IntIntOpenHashMap(); - - int[] vars = copiedVars.keys().toArray(); - Arrays.sort(vars); - List phisToAdd = new ArrayList<>(); - for (int var : vars) { - int varCopy = copiedVars.get(var); - - Phi phi = new Phi(); - phi.setReceiver(program.createVariable()); - phiMap.put(var, phi.getReceiver().getIndex()); - newHeadPhiMap.put(varCopy, phi.getReceiver().getIndex()); - phisToAdd.add(phi); - - for (int source : cfg.incomingEdges(bodyStart)) { - if (!nodes.contains(source)) { - continue; - } - - Incoming incoming = new Incoming(); - incoming.setValue(program.variableAt(var)); - incoming.setSource(program.basicBlockAt(source)); - phi.getIncomings().add(incoming); - - incoming = new Incoming(); - incoming.setValue(program.variableAt(varCopy)); - incoming.setSource(program.basicBlockAt(copiedNodes.get(source))); - phi.getIncomings().add(incoming); - } - } - - InstructionVariableMapper mapper = new InstructionVariableMapper(var -> { - int index = var.getIndex(); - return program.variableAt(phiMap.getOrDefault(index, index)); - }); - for (int node : nodes.toArray()) { - if (!copiedNodes.containsKey(node)) { - BasicBlock block = program.basicBlockAt(node); - mapper.apply(block); - } - } - - head.getPhis().addAll(phisToAdd); - } - - private void adjustOutputPhis() { - IntIntMap phiMap = new IntIntOpenHashMap(); - class PhiToAdd { - private final Phi phi; - private final BasicBlock target; - private PhiToAdd(Phi phi, BasicBlock target) { - this.phi = phi; - this.target = target; - } - } - List phis = new ArrayList<>(); - - int[] vars = copiedVars.keys().toArray(); - Arrays.sort(vars); - int[] exits = this.exits.toArray(); - Arrays.sort(exits); - - for (int exit : exits) { - for (int var : vars) { - int definedAt = varDefinitionPoints.get(var); - if (!dom.dominates(definedAt, exit)) { - continue; - } - - int varCopy = copiedVars.get(var); - int copiedAt = copiedNodes.get(definedAt); - for (int successor : cfg.outgoingEdges(exit)) { - if (nodes.contains(successor)) { - continue; - } - - Phi phi = new Phi(); - phi.setReceiver(program.createVariable()); - - Incoming originalInput = new Incoming(); - originalInput.setSource(program.basicBlockAt(definedAt)); - originalInput.setValue(program.variableAt(var)); - phi.getIncomings().add(originalInput); - - Incoming copyInput = new Incoming(); - copyInput.setSource(program.basicBlockAt(copiedAt)); - copyInput.setValue(program.variableAt(varCopy)); - phi.getIncomings().add(copyInput); - - phis.add(new PhiToAdd(phi, program.basicBlockAt(successor))); - phiMap.put(var, phi.getReceiver().getIndex()); - } - } - } - - InstructionVariableMapper mapper = new InstructionVariableMapper(var -> { - int index = var.getIndex(); - return program.variableAt(phiMap.getOrDefault(index, index)); - }); - for (int i = 0; i < cfg.size(); ++i) { - if (!nodes.contains(i)) { - mapper.apply(program.basicBlockAt(i)); - } - } - - for (PhiToAdd phiToAdd : phis) { - phiToAdd.target.getPhis().add(phiToAdd.phi); - } - } } } diff --git a/core/src/main/java/org/teavm/vm/TeaVM.java b/core/src/main/java/org/teavm/vm/TeaVM.java index 5c0a5ed80..d51c5bbf6 100644 --- a/core/src/main/java/org/teavm/vm/TeaVM.java +++ b/core/src/main/java/org/teavm/vm/TeaVM.java @@ -649,7 +649,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository { } private List getOptimizations() { - return Arrays.asList(new ArrayUnwrapMotion(), new LoopInversion(), new LoopInvariantMotion(), + return Arrays.asList(new ArrayUnwrapMotion(), /*new LoopInversion(),*/ new LoopInvariantMotion(), new GlobalValueNumbering(), new UnusedVariableElimination()); }