Adds variable usage extractor and phi eliminator (incomplete)

This commit is contained in:
konsoletyper 2014-01-09 17:30:39 +04:00
parent 559cf989ba
commit 2214433d6c
2 changed files with 297 additions and 0 deletions

View File

@ -0,0 +1,94 @@
/*
* Copyright 2014 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.javascript;
import java.util.ArrayList;
import java.util.List;
import org.teavm.model.*;
import org.teavm.model.util.InstructionTransitionExtractor;
import org.teavm.model.util.UsageExtractor;
/**
*
* @author Alexey Andreev
*/
class PhiEliminator {
public static void eliminatePhis(Program program) {
// Count how many times each variable is used
int[] variableUsageCount = new int[program.variableCount()];
int[] definitionRenamings = new int[program.variableCount()];
for (int i = 0; i < definitionRenamings.length; ++i) {
definitionRenamings[i] = i;
}
UsageExtractor usageExtractor = new UsageExtractor();
InstructionTransitionExtractor transitionExtractor = new InstructionTransitionExtractor();
int blockCount = program.basicBlockCount();
for (int i = 0; i < blockCount; ++i) {
BasicBlock block = program.basicBlockAt(i);
for (Instruction insn : block.getInstructions()) {
insn.acceptVisitor(usageExtractor);
for (Variable var : usageExtractor.getUsedVariables()) {
variableUsageCount[var.getIndex()]++;
}
}
for (Phi phi : block.getPhis()) {
for (Incoming incoming : phi.getIncomings()) {
variableUsageCount[incoming.getValue().getIndex()]++;
}
}
}
// Places assignments at the end of each block
for (int i = 0; i < blockCount; ++i) {
BasicBlock block = program.basicBlockAt(i);
block.getLastInstruction().acceptVisitor(transitionExtractor);
BasicBlock[] targets = transitionExtractor.getTargets();
if (targets.length == 1) {
} else {
for (BasicBlock targetBlock : transitionExtractor.getTargets()) {
List<Incoming> incomings = new ArrayList<>();
for (Incoming incoming : getIncomings(block, targetBlock)) {
if (variableUsageCount[incoming.getSource().getIndex()] <= 1) {
definitionRenamings[incoming.getValue().getIndex()] =
incoming.getPhi().getReceiver().getIndex();
} else {
incomings.add(incoming);
}
}
}
}
}
// Removes phi functions
for (int i = 0; i < blockCount; ++i) {
BasicBlock block = program.basicBlockAt(i);
block.getPhis().clear();
}
}
private static List<Incoming> getIncomings(BasicBlock block, BasicBlock targetBlock) {
List<Incoming> incomings = new ArrayList<>();
for (Phi phi : targetBlock.getPhis()) {
for (Incoming incoming : phi.getIncomings()) {
if (incoming.getSource() == block) {
incomings.add(incoming);
}
}
}
return incomings;
}
}

View File

@ -0,0 +1,203 @@
/*
* Copyright 2014 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.util;
import org.teavm.model.Variable;
import org.teavm.model.instructions.*;
/**
*
* @author Alexey Andreev
*/
public class UsageExtractor implements InstructionVisitor {
private Variable[] usedVariables;
public Variable[] getUsedVariables() {
return usedVariables;
}
@Override
public void visit(EmptyInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(ClassConstantInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(NullConstantInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(IntegerConstantInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(LongConstantInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(FloatConstantInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(DoubleConstantInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(StringConstantInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(BinaryInstruction insn) {
usedVariables = new Variable[] { insn.getFirstOperand(), insn.getSecondOperand() };
}
@Override
public void visit(NegateInstruction insn) {
usedVariables = new Variable[] { insn.getOperand() };
}
@Override
public void visit(AssignInstruction insn) {
usedVariables = new Variable[] { insn.getAssignee() };
}
@Override
public void visit(CastInstruction insn) {
usedVariables = new Variable[] { insn.getValue() };
}
@Override
public void visit(CastNumberInstruction insn) {
usedVariables = new Variable[] { insn.getValue() };
}
@Override
public void visit(CastIntegerInstruction insn) {
usedVariables = new Variable[] { insn.getValue() };
}
@Override
public void visit(BranchingInstruction insn) {
usedVariables = new Variable[] { insn.getOperand() };
}
@Override
public void visit(BinaryBranchingInstruction insn) {
usedVariables = new Variable[] { insn.getFirstOperand(), insn.getSecondOperand() };
}
@Override
public void visit(JumpInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(SwitchInstruction insn) {
usedVariables = new Variable[] { insn.getCondition() };
}
@Override
public void visit(ExitInstruction insn) {
usedVariables = insn.getValueToReturn() != null ? new Variable[] { insn.getValueToReturn() } : new Variable[0];
}
@Override
public void visit(RaiseInstruction insn) {
usedVariables = new Variable[] { insn.getException() };
}
@Override
public void visit(ConstructArrayInstruction insn) {
usedVariables = new Variable[] { insn.getSize() };
}
@Override
public void visit(ConstructInstruction insn) {
usedVariables = new Variable[0];
}
@Override
public void visit(ConstructMultiArrayInstruction insn) {
usedVariables = insn.getDimensions().toArray(new Variable[0]);
}
@Override
public void visit(GetFieldInstruction insn) {
usedVariables = insn.getInstance() != null ? new Variable[] { insn.getInstance() } : new Variable[0];
}
@Override
public void visit(PutFieldInstruction insn) {
usedVariables = insn.getInstance() != null ? new Variable[] { insn.getInstance(), insn.getValue() } :
new Variable[] { insn.getValue() };
}
@Override
public void visit(ArrayLengthInstruction insn) {
usedVariables = new Variable[] { insn.getArray() };
}
@Override
public void visit(CloneArrayInstruction insn) {
usedVariables = new Variable[] { insn.getArray() };
}
@Override
public void visit(UnwrapArrayInstruction insn) {
usedVariables = new Variable[] { insn.getArray() };
}
@Override
public void visit(GetElementInstruction insn) {
usedVariables = new Variable[] { insn.getArray(), insn.getIndex() };
}
@Override
public void visit(PutElementInstruction insn) {
usedVariables = new Variable[] { insn.getArray(), insn.getIndex(), insn.getValue() };
}
@Override
public void visit(InvokeInstruction insn) {
if (insn.getInstance() != null) {
usedVariables = new Variable[insn.getArguments().size() + 1];
usedVariables[insn.getArguments().size()] = insn.getInstance();
} else {
usedVariables = new Variable[insn.getArguments().size()];
}
insn.getArguments().toArray(usedVariables);
}
@Override
public void visit(IsInstanceInstruction insn) {
usedVariables = new Variable[] { insn.getValue() };
}
@Override
public void visit(InitClassInstruction insn) {
usedVariables = new Variable[0];
}
}