Merge "Avoid to compute dominator tree when is not useful"
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index bed4df3..a54208d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -1932,43 +1932,65 @@
return ch0.equals(ch1);
}
- public void commonSubexpressionElimination(IRCode code) {
- final ListMultimap<Wrapper<Instruction>, Value> instructionToValue = ArrayListMultimap.create();
- final DominatorTree dominatorTree = new DominatorTree(code);
- final CSEExpressionEquivalence equivalence = new CSEExpressionEquivalence(code);
+ private boolean isCSEInstructionCandidate(Instruction instruction) {
+ return (instruction.isBinop()
+ || instruction.isUnop()
+ || instruction.isInstanceOf()
+ || instruction.isCheckCast())
+ && instruction.getLocalInfo() == null
+ && !instruction.hasInValueWithLocalInfo();
+ }
- for (int i = 0; i < dominatorTree.getSortedBlocks().length; i++) {
- BasicBlock block = dominatorTree.getSortedBlocks()[i];
+ private boolean hasCSECandidate(IRCode code, int noCandidate) {
+ for (BasicBlock block : code.blocks) {
InstructionListIterator iterator = block.listIterator();
while (iterator.hasNext()) {
- Instruction instruction = iterator.next();
- if (instruction.isBinop()
- || instruction.isUnop()
- || instruction.isInstanceOf()
- || instruction.isCheckCast()) {
- if (instruction.getLocalInfo() != null || instruction.hasInValueWithLocalInfo()) {
- // If the instruction has input or output values then it is not safe to share it.
- continue;
- }
- List<Value> candidates = instructionToValue.get(equivalence.wrap(instruction));
- boolean eliminated = false;
- if (candidates.size() > 0) {
- for (Value candidate : candidates) {
- if (dominatorTree.dominatedBy(block, candidate.definition.getBlock()) &&
- shareCatchHandlers(instruction, candidate.definition)) {
- instruction.outValue().replaceUsers(candidate);
- eliminated = true;
- iterator.removeOrReplaceByDebugLocalRead();
- break; // Don't try any more candidates.
+ if (isCSEInstructionCandidate(iterator.next())) {
+ return true;
+ }
+ }
+ block.mark(noCandidate);
+ }
+ return false;
+ }
+
+ public void commonSubexpressionElimination(IRCode code) {
+ int noCandidate = code.reserveMarkingColor();
+ if (hasCSECandidate(code, noCandidate)) {
+ final ListMultimap<Wrapper<Instruction>, Value> instructionToValue =
+ ArrayListMultimap.create();
+ final CSEExpressionEquivalence equivalence = new CSEExpressionEquivalence(code);
+ final DominatorTree dominatorTree = new DominatorTree(code);
+ for (int i = 0; i < dominatorTree.getSortedBlocks().length; i++) {
+ BasicBlock block = dominatorTree.getSortedBlocks()[i];
+ if (block.isMarked(noCandidate)) {
+ continue;
+ }
+ InstructionListIterator iterator = block.listIterator();
+ while (iterator.hasNext()) {
+ Instruction instruction = iterator.next();
+ if (isCSEInstructionCandidate(instruction)) {
+ List<Value> candidates = instructionToValue.get(equivalence.wrap(instruction));
+ boolean eliminated = false;
+ if (candidates.size() > 0) {
+ for (Value candidate : candidates) {
+ if (dominatorTree.dominatedBy(block, candidate.definition.getBlock())
+ && shareCatchHandlers(instruction, candidate.definition)) {
+ instruction.outValue().replaceUsers(candidate);
+ eliminated = true;
+ iterator.removeOrReplaceByDebugLocalRead();
+ break; // Don't try any more candidates.
+ }
}
}
- }
- if (!eliminated) {
- instructionToValue.put(equivalence.wrap(instruction), instruction.outValue());
+ if (!eliminated) {
+ instructionToValue.put(equivalence.wrap(instruction), instruction.outValue());
+ }
}
}
}
}
+ code.returnMarkingColor(noCandidate);
assert code.isConsistentSSA();
}