From 31b95253095f72a7a121a629a68a850a93a5a475 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Fri, 21 Feb 2014 15:07:37 +0400 Subject: [PATCH] Fixes bugs. Adds JCL implementation --- teavm-classlib/pom.xml | 3 + .../teavm/classlib/java/util/TArrayList.java | 6 +- .../org/teavm/classlib/java/util/TArrays.java | 95 ++++++++ .../classlib/java/util/TCollections.java | 135 +++++++++++ .../teavm/classlib/java/util/TComparator.java | 6 +- .../java/lang/util/ArrayListTest.java | 29 +++ .../classlib/java/lang/util/ArraysTest.java | 47 ++++ .../java/org/teavm/common/GraphBuilder.java | 4 +- .../teavm/dependency/DependencyChecker.java | 1 - .../DependencyNodeToNodeTransition.java | 4 +- .../model/util/InstructionVariableMapper.java | 226 ++++++++++++++++++ .../teavm/model/util/RegisterAllocator.java | 8 +- .../teavm/optimization/ClassSetOptimizer.java | 2 +- .../CommonSubexpressionElimination.java | 57 +++-- 14 files changed, 591 insertions(+), 32 deletions(-) create mode 100644 teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java create mode 100644 teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArraysTest.java create mode 100644 teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java diff --git a/teavm-classlib/pom.xml b/teavm-classlib/pom.xml index 1bf13a0ec..da8355cad 100644 --- a/teavm-classlib/pom.xml +++ b/teavm-classlib/pom.xml @@ -54,6 +54,9 @@ false 1 + + **.ArraysTest + diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java index 761cf083e..943794448 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrayList.java @@ -128,10 +128,10 @@ public class TArrayList extends TAbstractList implements TCloneable, TSeri } ensureCapacity(size + c.size()); int gap = c.size(); - size += gap; - for (int i = gap - 1; i > index; --i) { - array[i] = array[i - gap]; + for (int i = size - 1; i >= index; --i) { + array[i + gap] = array[i]; } + size += gap; TIterator iter = c.iterator(); for (int i = 0; i < gap; ++i) { array[index++] = iter.next(); diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java index 9cc2a55d3..10598dd18 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TArrays.java @@ -182,4 +182,99 @@ public class TArrays extends TObject { public static void fill(TObject[] a, TObject val) { fill(a, 0, a.length, val); } + + + public static void sort(Object[] a) { + sort(a, new NaturalOrder()); + } + + public static void sort(Object[] a, int fromIndex, int toIndex) { + sort(a, fromIndex, toIndex, new NaturalOrder()); + } + + private static class NaturalOrder implements TComparator { + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override public int compare(Object o1, Object o2) { + if (o1 != null) { + return ((TComparable)o1).compareTo((TComparable)o2); + } else if (o2 != null) { + return ((TComparable)o2).compareTo((TComparable)o1); + } else { + return 0; + } + } + } + + public static void sort(T[] a, int fromIndex, int toIndex, TComparator c) { + @SuppressWarnings("unchecked") + T[] subarray = (T[])new Object[toIndex - fromIndex]; + for (int i = fromIndex; i < toIndex; ++i) { + subarray[i - fromIndex] = a[i]; + } + sort(subarray, c); + for (int i = fromIndex; i < toIndex; ++i) { + a[i] = subarray[i - fromIndex]; + } + } + + @SuppressWarnings("unchecked") + public static void sort(T[] a, TComparator c) { + Object[] first = a; + Object[] second = new Object[a.length]; + int chunkSize = 1; + while (chunkSize < a.length) { + for (int i = 0; i < first.length; i += chunkSize * 2) { + merge(first, second, i, Math.min(first.length, i + chunkSize), + Math.min(first.length, i + 2 * chunkSize), (TComparator)c); + } + Object[] tmp = first; + first = second; + second = tmp; + chunkSize *= 2; + } + if (first != a) { + for (int i = 0; i < first.length; ++i) { + second[i] = first[i]; + } + } + } + + private static void merge(Object[] a, Object[] b, int from, int split, int to, TComparator comp) { + int index = from; + int from2 = split; + while (true) { + if (from == split) { + while (from2 < to) { + b[index++] = a[from2++]; + } + break; + } else if (from2 == to) { + while (from < split) { + b[index++] = a[from++]; + } + break; + } + Object p = a[from]; + Object q = a[from2]; + if (comp.compare(p, q) <= 0) { + b[index++] = p; + ++from; + } else { + b[index++] = q; + ++from2; + } + } + } + + @SafeVarargs + public static TList asList(final T... a) { + return new TAbstractList() { + @Override public T get(int index) { + return a[index]; + } + @Override public int size() { + return a.length; + } + }; + } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java new file mode 100644 index 000000000..ef02b031c --- /dev/null +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TCollections.java @@ -0,0 +1,135 @@ +/* + * 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.classlib.java.util; + +import org.teavm.classlib.java.lang.*; + +/** + * + * @author Alexey Andreev + */ +public class TCollections extends TObject { + public static TIterator emptyIterator() { + return new TIterator() { + @Override public boolean hasNext() { + return false; + } + @Override public T next() { + throw new TNoSuchElementException(); + } + @Override public void remove() { + throw new TIllegalStateException(); + } + }; + } + + public static TListIterator emptyListIterator() { + return new TListIterator() { + @Override public boolean hasNext() { + return false; + } + @Override public T next() { + throw new TNoSuchElementException(); + } + @Override public void remove() { + throw new TIllegalStateException(); + } + @Override public boolean hasPrevious() { + return false; + } + @Override public T previous() { + throw new TNoSuchElementException(); + } + @Override public int nextIndex() { + return 0; + } + @Override public int previousIndex() { + return -1; + } + @Override public void set(T e) { + throw new TUnsupportedOperationException(); + } + @Override public void add(T e) { + throw new TUnsupportedOperationException(); + } + }; + } + + public static final TList emptyList() { + return new TAbstractList() { + @Override public T get(int index) { + throw new TIndexOutOfBoundsException(); + } + @Override public int size() { + return 0; + } + }; + } + + public static TList singletonList(final T o) { + return new TAbstractList() { + @Override public T get(int index) { + if (index != 0) { + throw new TIndexOutOfBoundsException(); + } + return o; + } + @Override public int size() { + return 1; + } + }; + } + + public static TList nCopies(final int n, final T o) { + return new TAbstractList() { + @Override public T get(int index) { + if (index < 0 || index >= n) { + throw new TIndexOutOfBoundsException(); + } + return o; + } + @Override public int size() { + return n; + } + }; + } + + public static void swap(TList list, int i, int j) { + @SuppressWarnings("unchecked") + TList objList = (TList)list; + Object tmp = objList.get(i); + objList.set(i, objList.get(j)); + objList.set(j, tmp); + } + + public static void sort(TList list, TComparator c) { + @SuppressWarnings("unchecked") + T[] array = (T[])new Object[list.size()]; + list.toArray(array); + TArrays.sort(array, c); + for (int i = 0; i < array.length; ++i) { + list.set(i, array[i]); + } + } + + public static > void sort(TList list) { + sort(list, new TComparator() { + @Override public int compare(T o1, T o2) { + return o1 != null ? o1.compareTo(o2) : -o2.compareTo(o1); + } + }); + } +} diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TComparator.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TComparator.java index 1e8435af6..9cd08220f 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TComparator.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/util/TComparator.java @@ -15,14 +15,10 @@ */ package org.teavm.classlib.java.util; -import org.teavm.classlib.java.lang.TObject; - /** * * @author Alexey Andreev */ -public interface TComparator { +public interface TComparator { int compare(T o1, T o2); - - boolean equals(TObject obj); } diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArrayListTest.java b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArrayListTest.java index 57ca456ad..ac15aaaee 100644 --- a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArrayListTest.java +++ b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArrayListTest.java @@ -78,6 +78,35 @@ public class ArrayListTest { } } + @Test + public void manyElementsAdded() { + List list = fillFromZeroToNine(); + list.addAll(3, fillFromZeroToNine()); + assertEquals(20, list.size()); + assertEquals(Integer.valueOf(2), list.get(2)); + assertEquals(Integer.valueOf(0), list.get(3)); + assertEquals(Integer.valueOf(9), list.get(12)); + assertEquals(Integer.valueOf(3), list.get(13)); + assertEquals(Integer.valueOf(9), list.get(19)); + } + + @Test + public void manyElementsRemoved() { + List list = fillFromZeroToNine(); + list.subList(2, 4).clear(); + assertEquals(8, list.size()); + assertEquals(Integer.valueOf(1), list.get(1)); + assertEquals(Integer.valueOf(4), list.get(2)); + assertEquals(Integer.valueOf(9), list.get(7)); + } + + @Test + public void elementIndexFound() { + List list = fillFromZeroToNine(); + assertEquals(3, list.indexOf(3)); + assertEquals(-1, list.indexOf(100)); + } + private List fillFromZeroToNine() { List list = new ArrayList<>(); for (int i = 0; i < 10; ++i) { diff --git a/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArraysTest.java b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArraysTest.java new file mode 100644 index 000000000..2fb4597dc --- /dev/null +++ b/teavm-classlib/src/test/java/org/teavm/classlib/java/lang/util/ArraysTest.java @@ -0,0 +1,47 @@ +/* + * 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.classlib.java.lang.util; + +import static org.junit.Assert.*; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; + +/** + * + * @author Alexey Andreev + */ +public class ArraysTest { + @Test + public void arraySorted() { + Integer[] array = { 2, 5, 7, 3, 5, 6 }; + Arrays.sort(array); + assertEquals(Integer.valueOf(2), array[0]); + assertEquals(Integer.valueOf(3), array[1]); + assertEquals(Integer.valueOf(5), array[2]); + assertEquals(Integer.valueOf(5), array[3]); + assertEquals(Integer.valueOf(6), array[4]); + assertEquals(Integer.valueOf(7), array[5]); + } + + @Test + public void arrayExposedAsList() { + Integer[] array = { 2, 3, 4 }; + List list = Arrays.asList(array); + assertEquals(3, list.size()); + assertEquals(Integer.valueOf(4), list.get(2)); + } +} diff --git a/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java b/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java index 4f6bfdd03..e3b965916 100644 --- a/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java @@ -43,8 +43,8 @@ public class GraphBuilder { } public void addEdge(int from, int to) { - if (to < 0) { - throw new IllegalArgumentException("To is negative: " + to); + if (to < 0 || from < 0) { + throw new IllegalArgumentException(); } sz = Math.max(sz, Math.max(from, to) + 1); builtGraph = null; diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java index b08c5d9ef..12c965910 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyChecker.java @@ -141,7 +141,6 @@ public class DependencyChecker implements DependencyInfo { } public void schedulePropagation(final DependencyConsumer consumer, final String type) { - System.out.print(""); executor.executeFast(new Runnable() { @Override public void run() { consumer.consume(type); diff --git a/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java b/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java index b13d1a467..d6be0a30a 100644 --- a/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java +++ b/teavm-core/src/main/java/org/teavm/dependency/DependencyNodeToNodeTransition.java @@ -41,8 +41,8 @@ class DependencyNodeToNodeTransition implements DependencyConsumer { } if (!destination.hasType(type)) { destination.propagate(type); - source.getArrayItem().connect(destination.getArrayItem()); - destination.getArrayItem().connect(source.getArrayItem()); } + source.getArrayItem().connect(destination.getArrayItem()); + destination.getArrayItem().connect(source.getArrayItem()); } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java b/teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java new file mode 100644 index 000000000..49eb8ca05 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/util/InstructionVariableMapper.java @@ -0,0 +1,226 @@ +/* + * 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 abstract class InstructionVariableMapper implements InstructionVisitor { + protected abstract Variable map(Variable var); + + @Override + public void visit(EmptyInstruction insn) { + } + + @Override + public void visit(ClassConstantInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(NullConstantInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(IntegerConstantInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(LongConstantInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(FloatConstantInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(DoubleConstantInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(StringConstantInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(BinaryInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setFirstOperand(map(insn.getFirstOperand())); + insn.setSecondOperand(map(insn.getSecondOperand())); + } + + @Override + public void visit(NegateInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setOperand(map(insn.getOperand())); + } + + @Override + public void visit(AssignInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setAssignee(map(insn.getAssignee())); + } + + @Override + public void visit(CastInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setValue(map(insn.getValue())); + } + + @Override + public void visit(CastNumberInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setValue(map(insn.getValue())); + } + + @Override + public void visit(CastIntegerInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setValue(map(insn.getValue())); + } + + @Override + public void visit(BranchingInstruction insn) { + insn.setOperand(map(insn.getOperand())); + } + + @Override + public void visit(BinaryBranchingInstruction insn) { + insn.setFirstOperand(map(insn.getFirstOperand())); + insn.setSecondOperand(map(insn.getSecondOperand())); + } + + @Override + public void visit(JumpInstruction insn) { + } + + @Override + public void visit(SwitchInstruction insn) { + insn.setCondition(insn.getCondition()); + } + + @Override + public void visit(ExitInstruction insn) { + if (insn.getValueToReturn() != null) { + insn.setValueToReturn(map(insn.getValueToReturn())); + } + } + + @Override + public void visit(RaiseInstruction insn) { + insn.setException(map(insn.getException())); + } + + @Override + public void visit(ConstructArrayInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setSize(map(insn.getSize())); + } + + @Override + public void visit(ConstructInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(ConstructMultiArrayInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + for (int i = 0; i < insn.getDimensions().size(); ++i) { + insn.getDimensions().set(i, map(insn.getDimensions().get(i))); + } + } + + @Override + public void visit(GetFieldInstruction insn) { + if (insn.getInstance() != null) { + insn.setInstance(map(insn.getInstance())); + } + insn.setReceiver(map(insn.getReceiver())); + } + + @Override + public void visit(PutFieldInstruction insn) { + if (insn.getInstance() != null) { + insn.setInstance(map(insn.getInstance())); + } + insn.setValue(map(insn.getValue())); + } + + @Override + public void visit(ArrayLengthInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setArray(map(insn.getArray())); + } + + @Override + public void visit(CloneArrayInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setArray(map(insn.getArray())); + } + + @Override + public void visit(UnwrapArrayInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setArray(map(insn.getArray())); + } + + @Override + public void visit(GetElementInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setArray(map(insn.getArray())); + insn.setIndex(map(insn.getIndex())); + } + + @Override + public void visit(PutElementInstruction insn) { + insn.setValue(map(insn.getValue())); + insn.setArray(map(insn.getArray())); + insn.setIndex(map(insn.getIndex())); + } + + @Override + public void visit(InvokeInstruction insn) { + if (insn.getReceiver() != null) { + insn.setReceiver(map(insn.getReceiver())); + } + if (insn.getInstance() != null) { + insn.setInstance(map(insn.getInstance())); + } + for (int i = 0; i < insn.getArguments().size(); ++i) { + insn.getArguments().set(i, map(insn.getArguments().get(i))); + } + } + + @Override + public void visit(IsInstanceInstruction insn) { + insn.setReceiver(map(insn.getReceiver())); + insn.setValue(map(insn.getValue())); + } + + @Override + public void visit(InitClassInstruction insn) { + } + +} diff --git a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java index c991cfeb8..78d2fd03c 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java +++ b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java @@ -150,11 +150,15 @@ public class RegisterAllocator { copy.incoming.setValue(program.variableAt(copy.original)); for (MutableGraphEdge edge : interferenceGraph.get(varClass).getEdges() .toArray(new MutableGraphEdge[0])) { - edge.setFirst(interferenceGraph.get(newClass)); + if (edge.getFirst() != null) { + edge.setFirst(interferenceGraph.get(newClass)); + } } for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges() .toArray(new MutableGraphEdge[0])) { - edge.setFirst(interferenceGraph.get(newClass)); + if (edge.getFirst() != null) { + edge.setFirst(interferenceGraph.get(newClass)); + } } } } diff --git a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java index 4c7073f0f..c926727e6 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java +++ b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java @@ -36,7 +36,7 @@ public class ClassSetOptimizer { } private List getOptimizations() { - return Arrays.asList(new CommonSubexpressionElimination(), new UnusedVariableElimination()); + return Arrays.asList(new UnusedVariableElimination()); } public void optimizeAll(ListableClassHolderSource classSource) { diff --git a/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java b/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java index 916854413..397621e90 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java +++ b/teavm-core/src/main/java/org/teavm/optimization/CommonSubexpressionElimination.java @@ -15,7 +15,9 @@ */ package org.teavm.optimization; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.teavm.common.DominatorTree; import org.teavm.common.Graph; @@ -52,6 +54,7 @@ public class CommonSubexpressionElimination implements MethodOptimization { for (int i = 0; i < map.length; ++i) { map[i] = i; } + List> outgoings = findOutgoings(program); int[] stack = new int[cfg.size() * 2]; int top = 0; @@ -64,7 +67,7 @@ public class CommonSubexpressionElimination implements MethodOptimization { int v = stack[--top]; currentBlockIndex = v; BasicBlock block = program.basicBlockAt(v); - for (int i = 0; i < block.getPhis().size(); ++i) { + /*for (int i = 0; i < block.getPhis().size(); ++i) { Phi phi = block.getPhis().get(i); int sharedValue = -2; for (Incoming incoming : phi.getIncomings()) { @@ -77,32 +80,31 @@ public class CommonSubexpressionElimination implements MethodOptimization { } } if (sharedValue != -1) { - map[phi.getReceiver().getIndex()] = sharedValue; + if (sharedValue != -2) { + AssignInstruction assignInsn = new AssignInstruction(); + assignInsn.setReceiver(phi.getReceiver()); + assignInsn.setAssignee(program.variableAt(sharedValue)); + block.getInstructions().add(0, assignInsn); + } block.getPhis().remove(i--); } - } + }*/ for (int i = 0; i < block.getInstructions().size(); ++i) { Instruction currentInsn = block.getInstructions().get(i); currentInsn.acceptVisitor(optimizer); if (eliminate) { - block.getInstructions().remove(i--); + block.getInstructions().set(i, new EmptyInstruction()); eliminate = false; } } + for (Incoming incoming : outgoings.get(v)) { + int value = map[incoming.getValue().getIndex()]; + incoming.setValue(program.variableAt(value)); + } for (int succ : dom.outgoingEdges(v)) { stack[top++] = succ; } } - for (int v = 0; v < program.basicBlockCount(); ++v) { - BasicBlock block = program.basicBlockAt(v); - for (int i = 0; i < block.getPhis().size(); ++i) { - Phi phi = block.getPhis().get(i); - for (Incoming incoming : phi.getIncomings()) { - int value = map[incoming.getValue().getIndex()]; - incoming.setValue(program.variableAt(value)); - } - } - } for (int i = 0; i < map.length; ++i) { if (map[i] != i) { @@ -114,6 +116,21 @@ public class CommonSubexpressionElimination implements MethodOptimization { program = null; } + private List> findOutgoings(Program program) { + List> outgoings = new ArrayList<>(); + for (int i = 0; i < program.basicBlockCount(); ++i) { + outgoings.add(new ArrayList()); + } + for (int i = 0; i < program.basicBlockCount(); ++i) { + for (Phi phi : program.basicBlockAt(i).getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + outgoings.get(incoming.getSource().getIndex()).add(incoming); + } + } + } + return outgoings; + } + private void bind(int var, String value) { KnownValue known = knownValues.get(value); if (known != null && domTree.dominates(known.location, currentBlockIndex)) { @@ -166,16 +183,19 @@ public class CommonSubexpressionElimination implements MethodOptimization { int b = map[insn.getSecondOperand().getIndex()]; insn.setFirstOperand(program.variableAt(a)); insn.setSecondOperand(program.variableAt(b)); + boolean commutative = false; String value; switch (insn.getOperation()) { case ADD: value = "+"; + commutative = true; break; case SUBTRACT: value = "-"; break; case MULTIPLY: value = "*"; + commutative = true; break; case DIVIDE: value = "/"; @@ -188,12 +208,15 @@ public class CommonSubexpressionElimination implements MethodOptimization { break; case AND: value = "&"; + commutative = true; break; case OR: value = "|"; + commutative = true; break; case XOR: value = "^"; + commutative = true; break; case SHIFT_LEFT: value = "<<"; @@ -207,8 +230,10 @@ public class CommonSubexpressionElimination implements MethodOptimization { default: return; } - value = "@" + a + value + "@" + b; - bind(insn.getReceiver().getIndex(), value); + bind(insn.getReceiver().getIndex(), "@" + a + value + "@" + b); + if (commutative) { + bind(insn.getReceiver().getIndex(), "@" + b + value + "@" + a); + } } @Override