Extend shorten live ranges to values used in invoke/range
Bug: b/302281605
Change-Id: I07c8100929435bf2676c7a8ef796f22d168fbd7c
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/DexConstantOptimizer.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/DexConstantOptimizer.java
index e4845ca..25fd979 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/DexConstantOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/DexConstantOptimizer.java
@@ -244,11 +244,7 @@
LinkedList<BasicBlock> blocks = code.blocks;
for (BasicBlock block : blocks) {
shortenLiveRangesInsideBlock(
- code,
- block,
- dominatorTreeMemoization,
- addConstantInBlock,
- canonicalizer::isConstantCanonicalizationCandidate);
+ code, block, dominatorTreeMemoization, addConstantInBlock, canonicalizer::isConstant);
}
// Heuristic to decide if constant instructions are shared in dominator block
@@ -446,10 +442,13 @@
DominatorTree dominatorTree = dominatorTreeMemoization.computeIfAbsent();
BasicBlock dominator = dominatorTree.closestDominator(userBlocks);
+ // Do not move the constant if the constant instruction can throw and the dominator or the
+ // original block has catch handlers, or if the code may have monitor instructions, since this
+ // could lead to verification errors.
if (instruction.instructionTypeCanThrow()) {
- if (block.hasCatchHandlers() || dominator.hasCatchHandlers()) {
- // Do not move the constant if the constant instruction can throw
- // and the dominator or the original block has catch handlers.
+ if (block.hasCatchHandlers()
+ || dominator.hasCatchHandlers()
+ || code.metadata().mayHaveMonitorInstruction()) {
continue;
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
index cdd49d1..1b14342 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/ConstantCanonicalizer.java
@@ -403,6 +403,27 @@
}
public boolean isConstantCanonicalizationCandidate(Instruction instruction) {
+ if (!isConstant(instruction)) {
+ return false;
+ }
+ // Do not canonicalize throwing instructions if there are monitor operations in the code.
+ // That could lead to unbalanced locking and could lead to situations where OOM exceptions
+ // could leave a synchronized method without unlocking the monitor.
+ if (instruction.instructionTypeCanThrow() && code.metadata().mayHaveMonitorInstruction()) {
+ return false;
+ }
+ // Constants that are used by invoke range are not canonicalized to be compliant with the
+ // optimization splitRangeInvokeConstant that gives the register allocator more freedom in
+ // assigning register to ranged invokes which can greatly reduce the number of register
+ // needed (and thereby code size as well). Thus no need to do a transformation that should
+ // be removed later by another optimization.
+ if (constantUsedByInvokeRange(instruction)) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isConstant(Instruction instruction) {
// Interested only in instructions types that can be canonicalized, i.e., ConstClass,
// ConstNumber, (DexItemBased)?ConstString, InstanceGet and StaticGet.
switch (instruction.opcode()) {
@@ -460,20 +481,6 @@
if (instruction.outValue().hasLocalInfo()) {
return false;
}
- // Do not canonicalize throwing instructions if there are monitor operations in the code.
- // That could lead to unbalanced locking and could lead to situations where OOM exceptions
- // could leave a synchronized method without unlocking the monitor.
- if (instruction.instructionTypeCanThrow() && code.metadata().mayHaveMonitorInstruction()) {
- return false;
- }
- // Constants that are used by invoke range are not canonicalized to be compliant with the
- // optimization splitRangeInvokeConstant that gives the register allocator more freedom in
- // assigning register to ranged invokes which can greatly reduce the number of register
- // needed (and thereby code size as well). Thus no need to do a transformation that should
- // be removed later by another optimization.
- if (constantUsedByInvokeRange(instruction)) {
- return false;
- }
return true;
}