mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-12-15 02:10:30 +08:00
Adds variable usage extractor and phi eliminator (incomplete)
This commit is contained in:
parent
559cf989ba
commit
2214433d6c
@ -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;
|
||||
}
|
||||
}
|
@ -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];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user