Merge "Utility to visit classes top-down"
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index ea6cac0..5436f0b 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -41,6 +41,7 @@
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.CodeRewriter;
import com.android.tools.r8.ir.optimize.DeadCodeRemover;
+import com.android.tools.r8.ir.optimize.peepholes.BasicBlockMuncher;
import com.android.tools.r8.utils.InternalOptions;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
@@ -135,6 +136,8 @@
new DeadCodeRemover(code, rewriter, graphLense, options).run();
LoadStoreHelper loadStoreHelper = new LoadStoreHelper(code, types);
loadStoreHelper.insertLoadsAndStores();
+ BasicBlockMuncher muncher = new BasicBlockMuncher();
+ muncher.optimize(code);
removeUnneededLoadsAndStores();
registerAllocator = new CfRegisterAllocator(code, options);
registerAllocator.allocateRegisters();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
new file mode 100644
index 0000000..9528401
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockMuncher.java
@@ -0,0 +1,35 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.peepholes;
+
+import com.android.tools.r8.ir.code.BasicBlock;
+import com.android.tools.r8.ir.code.IRCode;
+import com.android.tools.r8.ir.code.InstructionListIterator;
+import java.util.Arrays;
+import java.util.List;
+
+public class BasicBlockMuncher {
+
+ private final List<BasicBlockPeephole> peepholes = Arrays.asList();
+
+ public void optimize(IRCode code) {
+ for (BasicBlock block : code.blocks) {
+ InstructionListIterator it = block.listIterator(block.getInstructions().size());
+ boolean matched = true;
+ while (matched || it.hasPrevious()) {
+ if (!it.hasPrevious()) {
+ matched = false;
+ it = block.listIterator(block.getInstructions().size());
+ }
+ for (BasicBlockPeephole peepHole : peepholes) {
+ matched |= peepHole.match(it);
+ }
+ if (it.hasPrevious()) {
+ it.previous();
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockPeephole.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockPeephole.java
new file mode 100644
index 0000000..a957334
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/BasicBlockPeephole.java
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.peepholes;
+
+import com.android.tools.r8.ir.code.InstructionListIterator;
+
+public interface BasicBlockPeephole {
+ boolean match(InstructionListIterator it);
+}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/peepholes/PeepholeHelper.java b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/PeepholeHelper.java
new file mode 100644
index 0000000..55078e3
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/ir/optimize/peepholes/PeepholeHelper.java
@@ -0,0 +1,60 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.ir.optimize.peepholes;
+
+import com.android.tools.r8.ir.code.Instruction;
+import com.android.tools.r8.ir.code.InstructionListIterator;
+import java.util.function.Predicate;
+
+public class PeepholeHelper {
+
+ public static class PeepholeLayout {
+ private Instruction[] instructions;
+ private Predicate<Instruction>[] predicates;
+
+ public PeepholeLayout(Instruction[] instructions, Predicate<Instruction>... predicates) {
+ this.instructions = instructions;
+ this.predicates = predicates;
+ }
+
+ public Instruction[] test(InstructionListIterator it) {
+ int index = 0;
+ boolean success = true;
+ for (Predicate<Instruction> p : predicates) {
+ if (!it.hasNext()) {
+ success = false;
+ break;
+ }
+ int insertIndex = index++;
+ instructions[insertIndex] = it.next();
+ if (!p.test(instructions[insertIndex])) {
+ success = false;
+ break;
+ }
+ }
+ for (int i = 0; i < index; i++) {
+ it.previous();
+ }
+ return success ? instructions : null;
+ }
+ }
+
+ public static PeepholeLayout getLayout(Predicate<Instruction>... predicates) {
+ Instruction[] arr = new Instruction[predicates.length];
+ return new PeepholeLayout(arr, predicates);
+ }
+
+ public static void swapNextTwoInstructions(InstructionListIterator it) {
+ assert it.hasNext();
+ Instruction moveForward = it.next();
+ Instruction moveBack = it.next();
+ it.set(moveForward);
+ // Two calls to previous is needed because the iterator moves between elements.
+ it.previous();
+ it.previous();
+ it.set(moveBack);
+ it.next();
+ }
+}