Fix const type of null constants from int to object. Various optimizations consider constants the same if they have the same type and value. Having null be of type int makes it possible for the optimizations to collaps a const 0 instruction of type int with a const 0 instruction that represents null. Correctly marking null constants as having type object fixes the issue. R=sgjesse@google.com Bug: 64740479 Change-Id: I16a3cddda673865f1ddc57e1dbf0a422dc912e27
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java index e376361..ef5a025 100644 --- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java +++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -26,7 +26,6 @@ // are all for fixed register values. All other values that are used as the destination for // const number instructions should be marked as constants. assert dest.isFixedRegisterValue() || dest.definition.isConstNumber(); - assert type != ConstType.OBJECT; this.type = type; this.value = value; } @@ -50,7 +49,7 @@ } public int getIntValue() { - assert type == ConstType.INT || type == ConstType.INT_OR_FLOAT; + assert type == ConstType.INT || type == ConstType.INT_OR_FLOAT || type == ConstType.OBJECT; return (int) value; } @@ -101,7 +100,7 @@ } int register = builder.allocatedRegister(dest(), getNumber()); - if (MoveType.fromConstType(type) == MoveType.SINGLE) { + if (MoveType.fromConstType(type) == MoveType.SINGLE || type == ConstType.OBJECT) { assert NumberUtils.is32Bit(value); if ((register & 0xf) == register && NumberUtils.is4Bit(value)) { builder.add(this, new Const4(register, (int) value));
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java index 32159c1..01ce6a4 100644 --- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java +++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -724,7 +724,7 @@ } public void addNullConst(int dest, long value) { - canonicalizeAndAddConst(ConstType.INT, dest, value, nullConstants); + canonicalizeAndAddConst(ConstType.OBJECT, dest, value, nullConstants); } public void addConstClass(int dest, DexType type) {
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 328c724..ec61f43 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
@@ -87,6 +87,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -1122,7 +1123,7 @@ if (current.isInvoke() && current.asInvoke().requiredArgumentRegisters() > 5) { Invoke invoke = current.asInvoke(); it.previous(); - Map<ConstNumber, ConstNumber> oldToNew = new HashMap<>(); + Map<ConstNumber, ConstNumber> oldToNew = new IdentityHashMap<>(); for (int i = 0; i < invoke.inValues().size(); i++) { Value value = invoke.inValues().get(i); if (value.isConstNumber() && value.numberOfUsers() > 1) {