Introduce a distinct ValueType for the single-or-null-object case.
Change-Id: I067e31349f3a31a55a8469130fd32813cd18f3d0
diff --git a/src/main/java/com/android/tools/r8/code/Const.java b/src/main/java/com/android/tools/r8/code/Const.java
index 7f9d8b8..1d8313d 100644
--- a/src/main/java/com/android/tools/r8/code/Const.java
+++ b/src/main/java/com/android/tools/r8/code/Const.java
@@ -57,6 +57,8 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(ValueType.INT_OR_FLOAT, AA, decodedValue());
+ int value = decodedValue();
+ ValueType type = value == 0 ? ValueType.INT_OR_FLOAT_OR_NULL : ValueType.INT_OR_FLOAT;
+ builder.addConst(type, AA, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Const16.java b/src/main/java/com/android/tools/r8/code/Const16.java
index baa51ea..24dae68 100644
--- a/src/main/java/com/android/tools/r8/code/Const16.java
+++ b/src/main/java/com/android/tools/r8/code/Const16.java
@@ -51,6 +51,8 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(ValueType.INT_OR_FLOAT, AA, decodedValue());
+ int value = decodedValue();
+ ValueType type = value == 0 ? ValueType.INT_OR_FLOAT_OR_NULL : ValueType.INT_OR_FLOAT;
+ builder.addConst(type, AA, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Const4.java b/src/main/java/com/android/tools/r8/code/Const4.java
index 31364ea..497a9ed 100644
--- a/src/main/java/com/android/tools/r8/code/Const4.java
+++ b/src/main/java/com/android/tools/r8/code/Const4.java
@@ -57,6 +57,8 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(ValueType.INT_OR_FLOAT, A, decodedValue());
+ int value = decodedValue();
+ ValueType type = value == 0 ? ValueType.INT_OR_FLOAT_OR_NULL : ValueType.INT_OR_FLOAT;
+ builder.addConst(type, A, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/ConstHigh16.java b/src/main/java/com/android/tools/r8/code/ConstHigh16.java
index 6cf0851..ecaf61f 100644
--- a/src/main/java/com/android/tools/r8/code/ConstHigh16.java
+++ b/src/main/java/com/android/tools/r8/code/ConstHigh16.java
@@ -57,6 +57,8 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addConst(ValueType.INT_OR_FLOAT, AA, decodedValue());
+ int value = decodedValue();
+ ValueType type = value == 0 ? ValueType.INT_OR_FLOAT_OR_NULL : ValueType.INT_OR_FLOAT;
+ builder.addConst(type, AA, value);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Format21t.java b/src/main/java/com/android/tools/r8/code/Format21t.java
index acd444b..9f15752 100644
--- a/src/main/java/com/android/tools/r8/code/Format21t.java
+++ b/src/main/java/com/android/tools/r8/code/Format21t.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -61,7 +62,7 @@
public void buildIR(IRBuilder builder) {
int offset = getOffset();
int size = getSize();
- builder.addIfZero(getType(), AA, offset + BBBB, offset + size);
+ builder.addIfZero(getType(), ValueType.INT_OR_FLOAT_OR_NULL, AA, offset + BBBB, offset + size);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/Format22t.java b/src/main/java/com/android/tools/r8/code/Format22t.java
index 21b7dcd..9bf727c 100644
--- a/src/main/java/com/android/tools/r8/code/Format22t.java
+++ b/src/main/java/com/android/tools/r8/code/Format22t.java
@@ -7,6 +7,7 @@
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.naming.ClassNameMapper;
import java.nio.ShortBuffer;
@@ -56,6 +57,8 @@
public abstract Type getType();
+ public abstract ValueType getOperandType();
+
@Override
public int[] getTargets() {
return new int[]{CCCC, getSize()};
@@ -65,7 +68,7 @@
public void buildIR(IRBuilder builder) {
int offset = getOffset();
int size = getSize();
- builder.addIf(getType(), A, B, offset + CCCC, offset + size);
+ builder.addIf(getType(), getOperandType(), A, B, offset + CCCC, offset + size);
}
@Override
diff --git a/src/main/java/com/android/tools/r8/code/IfEq.java b/src/main/java/com/android/tools/r8/code/IfEq.java
index 4cedf62..7a75ebe 100644
--- a/src/main/java/com/android/tools/r8/code/IfEq.java
+++ b/src/main/java/com/android/tools/r8/code/IfEq.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.code;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
public class IfEq extends Format22t {
@@ -38,4 +39,9 @@
public Type getType() {
return Type.EQ;
}
+
+ @Override
+ public ValueType getOperandType() {
+ return ValueType.INT_OR_FLOAT_OR_NULL;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/code/IfGe.java b/src/main/java/com/android/tools/r8/code/IfGe.java
index 4946529..42d3740 100644
--- a/src/main/java/com/android/tools/r8/code/IfGe.java
+++ b/src/main/java/com/android/tools/r8/code/IfGe.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.code;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
public class IfGe extends Format22t {
@@ -38,4 +39,9 @@
public Type getType() {
return Type.GE;
}
+
+ @Override
+ public ValueType getOperandType() {
+ return ValueType.INT;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/code/IfGt.java b/src/main/java/com/android/tools/r8/code/IfGt.java
index 2d3f84a..ee4d9bd 100644
--- a/src/main/java/com/android/tools/r8/code/IfGt.java
+++ b/src/main/java/com/android/tools/r8/code/IfGt.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.code;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
public class IfGt extends Format22t {
@@ -38,4 +39,9 @@
public Type getType() {
return Type.GT;
}
+
+ @Override
+ public ValueType getOperandType() {
+ return ValueType.INT;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/code/IfLe.java b/src/main/java/com/android/tools/r8/code/IfLe.java
index 4710825..7b4e893 100644
--- a/src/main/java/com/android/tools/r8/code/IfLe.java
+++ b/src/main/java/com/android/tools/r8/code/IfLe.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.code;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
public class IfLe extends Format22t {
@@ -38,4 +39,9 @@
public Type getType() {
return Type.LE;
}
+
+ @Override
+ public ValueType getOperandType() {
+ return ValueType.INT;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/code/IfLt.java b/src/main/java/com/android/tools/r8/code/IfLt.java
index 631b971..78a04a5 100644
--- a/src/main/java/com/android/tools/r8/code/IfLt.java
+++ b/src/main/java/com/android/tools/r8/code/IfLt.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.code;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
public class IfLt extends Format22t {
@@ -38,4 +39,9 @@
public Type getType() {
return Type.LT;
}
+
+ @Override
+ public ValueType getOperandType() {
+ return ValueType.INT;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/code/IfNe.java b/src/main/java/com/android/tools/r8/code/IfNe.java
index d7004fd..5a97dfc 100644
--- a/src/main/java/com/android/tools/r8/code/IfNe.java
+++ b/src/main/java/com/android/tools/r8/code/IfNe.java
@@ -4,6 +4,7 @@
package com.android.tools.r8.code;
import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
public class IfNe extends Format22t {
@@ -38,4 +39,9 @@
public Type getType() {
return Type.NE;
}
+
+ @Override
+ public ValueType getOperandType() {
+ return ValueType.INT_OR_FLOAT_OR_NULL;
+ }
}
diff --git a/src/main/java/com/android/tools/r8/code/Move.java b/src/main/java/com/android/tools/r8/code/Move.java
index 0dc06f9..90e44f4 100644
--- a/src/main/java/com/android/tools/r8/code/Move.java
+++ b/src/main/java/com/android/tools/r8/code/Move.java
@@ -37,6 +37,6 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addMove(ValueType.INT_OR_FLOAT, A, B);
+ builder.addMove(ValueType.INT_OR_FLOAT_OR_NULL, A, B);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/Move16.java b/src/main/java/com/android/tools/r8/code/Move16.java
index aae6740..6772538 100644
--- a/src/main/java/com/android/tools/r8/code/Move16.java
+++ b/src/main/java/com/android/tools/r8/code/Move16.java
@@ -36,6 +36,6 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addMove(ValueType.INT_OR_FLOAT, AAAA, BBBB);
+ builder.addMove(ValueType.INT_OR_FLOAT_OR_NULL, AAAA, BBBB);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/MoveFrom16.java b/src/main/java/com/android/tools/r8/code/MoveFrom16.java
index 7d33a0b..a81a8a0 100644
--- a/src/main/java/com/android/tools/r8/code/MoveFrom16.java
+++ b/src/main/java/com/android/tools/r8/code/MoveFrom16.java
@@ -36,6 +36,6 @@
@Override
public void buildIR(IRBuilder builder) {
- builder.addMove(ValueType.INT_OR_FLOAT, AA, BBBB);
+ builder.addMove(ValueType.INT_OR_FLOAT_OR_NULL, AA, BBBB);
}
}
diff --git a/src/main/java/com/android/tools/r8/code/MoveType.java b/src/main/java/com/android/tools/r8/code/MoveType.java
index 6ade361..a9ff6e0 100644
--- a/src/main/java/com/android/tools/r8/code/MoveType.java
+++ b/src/main/java/com/android/tools/r8/code/MoveType.java
@@ -18,6 +18,7 @@
case INT:
case FLOAT:
case INT_OR_FLOAT:
+ case INT_OR_FLOAT_OR_NULL:
return SINGLE;
case LONG:
case DOUBLE:
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
index b089e46..2b02211 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlockInstructionIterator.java
@@ -471,12 +471,16 @@
if (normalExits.get(0).exit().asReturn().isReturnVoid()) {
newReturn = new Return();
} else {
+ ValueType returnType = null;
boolean same = true;
List<Value> operands = new ArrayList<>(normalExits.size());
for (BasicBlock exitBlock : normalExits) {
- Value retValue = exitBlock.exit().asReturn().returnValue();
+ Return exit = exitBlock.exit().asReturn();
+ Value retValue = exit.returnValue();
operands.add(retValue);
same = same && retValue == operands.get(0);
+ assert returnType == null || returnType == exit.getReturnType();
+ returnType = exit.getReturnType();
}
Value value;
if (same) {
@@ -486,12 +490,12 @@
new Phi(
code.valueNumberGenerator.next(),
newExitBlock,
- operands.get(0).outType(),
+ returnType,
null);
phi.addOperands(operands);
value = phi;
}
- newReturn = new Return(value, value.outType());
+ newReturn = new Return(value, returnType);
}
// The newly constructed return will be eliminated as part of inlining so we set position none.
newReturn.setPosition(Position.none());
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 ba5c27f..b887e97 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
@@ -38,7 +38,7 @@
}
private boolean preciseTypeUnknown() {
- return outType() == ValueType.INT_OR_FLOAT || outType() == ValueType.LONG_OR_DOUBLE;
+ return !outType().isPreciseType();
}
public Value dest() {
@@ -52,7 +52,8 @@
public int getIntValue() {
assert outType() == ValueType.INT
|| outType() == ValueType.INT_OR_FLOAT
- || outType() == ValueType.OBJECT;
+ || outType() == ValueType.INT_OR_FLOAT_OR_NULL
+ || outType() == ValueType.OBJECT; // Used for is-null conditionals.
return (int) value;
}
@@ -62,7 +63,9 @@
}
public float getFloatValue() {
- assert outType() == ValueType.FLOAT || outType() == ValueType.INT_OR_FLOAT;
+ assert outType() == ValueType.FLOAT
+ || outType() == ValueType.INT_OR_FLOAT
+ || outType() == ValueType.INT_OR_FLOAT_OR_NULL;
return Float.intBitsToFloat((int) value);
}
@@ -104,7 +107,7 @@
}
int register = builder.allocatedRegister(dest(), getNumber());
- if (outType().isSingle() || outType().isObject()) {
+ if (outType().isObjectOrSingle()) {
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/code/Phi.java b/src/main/java/com/android/tools/r8/ir/code/Phi.java
index 5a9673f..faab702 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Phi.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Phi.java
@@ -30,14 +30,6 @@
// contain this phi.
private List<Map<Integer, Value>> definitionUsers = new ArrayList<>();
- // The computed out type is not always the same as 'this.type' because of the type
- // confusion around null and constant zero. The null object can be used in a single
- // context (if tests) and the single 0 can be used as null. A phi can therefore
- // have either of the creation types 'single' and 'object' depending on the use that
- // triggered the creation of the phi. We therefore have to delay the output type
- // computation of the phi until all operands are known.
- private ValueType outType = null;
-
public Phi(int number, BasicBlock block, ValueType type, DebugLocalInfo local) {
super(number, type, local);
this.block = block;
@@ -245,6 +237,11 @@
}
builder.append(" <- phi");
StringUtils.append(builder, ListUtils.map(operands, Value::toString));
+ ValueType computed = computeOutType(null);
+ builder.append(" : ").append(type);
+ if (type != computed) {
+ builder.append(" / ").append(computed);
+ }
return builder.toString();
}
@@ -272,12 +269,6 @@
definitionUsers = null;
}
- private boolean isSingleConstZero(Value value) {
- return value.definition != null
- && value.outType().isSingle()
- && value.isZero();
- }
-
/**
* Determine if the only possible values for the phi are the integers 0 or 1.
*/
@@ -314,40 +305,53 @@
}
private ValueType computeOutType(Set<Phi> active) {
- if (outType != null) {
- return outType;
- }
- active.add(this);
// Go through non-phi operands first to determine if we have an operand that dictates the type.
for (Value operand : operands) {
// Since a constant zero can be either an integer or an Object (null) we skip them
// when computing types and rely on other operands to specify the actual type.
- if (!operand.isPhi() && !isSingleConstZero(operand)) {
- return operand.outType();
+ if (!operand.isPhi()) {
+ if (operand.outType() != ValueType.INT_OR_FLOAT_OR_NULL) {
+ return operand.outType();
+ }
+ assert operand.isZero();
}
}
// We did not find a non-phi operand that dictates the type. Recurse on phi arguments.
+ if (active == null) {
+ active = new HashSet<>();
+ }
+ active.add(this);
for (Value operand : operands) {
if (operand.isPhi() && !active.contains(operand.asPhi())) {
ValueType phiType = operand.asPhi().computeOutType(active);
- if (phiType != ValueType.INT_OR_FLOAT) {
+ if (phiType != ValueType.INT_OR_FLOAT_OR_NULL) {
return phiType;
}
}
}
- // All operands were the constant zero or phis with out type INT_OR_FLOAT and the DEX move type
- // is either object or single depending on the use. Since all inputs have out type INT_OF_FLOAT
- // it is safe to return ValueType.INT_OR_FLOAT here.
- assert type.isSingle() || type.isObject();
- return ValueType.INT_OR_FLOAT;
+ // All operands were the constant zero or phis with out type INT_OR_FLOAT_OR_NULL.
+ return ValueType.INT_OR_FLOAT_OR_NULL;
+ }
+
+ private static boolean verifyUnknownOrCompatible(ValueType known, ValueType computed) {
+ assert computed == ValueType.INT_OR_FLOAT_OR_NULL || known.compatible(computed);
+ return true;
}
@Override
public ValueType outType() {
- if (outType != null) {
- return outType;
+ if (type != ValueType.INT_OR_FLOAT_OR_NULL) {
+ assert verifyUnknownOrCompatible(type, computeOutType(null));
+ return type;
}
- return computeOutType(new HashSet<>());
+ // If the phi has unknown type (ie, INT_OR_FLOAT_OR_NULL) then it must be computed. This is
+ // because of the type confusion around null and constant zero. The null object can be used in
+ // a single context (if tests) and the single 0 can be used as null. If the instruction
+ // triggering the creation of a phi does not determine the type (eg, a move can be of int,
+ // float or zero/null) we need to compute the actual type based on the operands.
+ ValueType computedType = computeOutType(null);
+ assert computedType.isObjectOrSingle();
+ return computedType;
}
@Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Return.java b/src/main/java/com/android/tools/r8/ir/code/Return.java
index 6561d27..a197c87 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Return.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Return.java
@@ -29,6 +29,7 @@
public Return(Value value, ValueType returnType) {
super(null, value);
+ assert returnType != ValueType.INT_OR_FLOAT_OR_NULL;
this.returnType = returnType;
}
@@ -49,17 +50,17 @@
if (isReturnVoid()) {
return new ReturnVoid();
} else {
+ int register = builder.allocatedRegister(returnValue(), getNumber());
switch (MoveType.fromValueType(returnType)) {
case OBJECT:
- assert returnValue().outType().isObject() || returnValue().outType().isSingle();
- return new ReturnObject(builder.allocatedRegister(returnValue(), getNumber()));
+ assert returnValue().outType().isObjectOrNull();
+ return new ReturnObject(register);
case SINGLE:
- assert returnValue().outType().isSingle();
- return new com.android.tools.r8.code.Return(
- builder.allocatedRegister(returnValue(), getNumber()));
+ assert returnValue().outType().isSingleOrZero();
+ return new com.android.tools.r8.code.Return(register);
case WIDE:
assert returnValue().outType().isWide();
- return new ReturnWide(builder.allocatedRegister(returnValue(), getNumber()));
+ return new ReturnWide(register);
default:
throw new Unreachable();
}
diff --git a/src/main/java/com/android/tools/r8/ir/code/ValueType.java b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
index dd058f0..c41b062 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ValueType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ValueType.java
@@ -13,6 +13,7 @@
INT,
FLOAT,
INT_OR_FLOAT,
+ INT_OR_FLOAT_OR_NULL,
LONG,
DOUBLE,
LONG_OR_DOUBLE;
@@ -29,16 +30,34 @@
return this == LONG || this == DOUBLE || this == LONG_OR_DOUBLE;
}
- public int requiredRegisters() {
- return isWide() ? 2 : 1;
+ public boolean isObjectOrSingle() {
+ return !isWide();
+ }
+
+ public boolean isObjectOrNull() {
+ return isObject() || this == INT_OR_FLOAT_OR_NULL;
+ }
+
+ public boolean isSingleOrZero() {
+ return isSingle() || this == INT_OR_FLOAT_OR_NULL;
+ }
+
+ public boolean isPreciseType() {
+ return this != ValueType.INT_OR_FLOAT
+ && this != ValueType.LONG_OR_DOUBLE
+ && this != ValueType.INT_OR_FLOAT_OR_NULL;
}
public boolean compatible(ValueType other) {
- return (isObject() && other.isObject())
+ return this == other
|| (isSingle() && other.isSingle())
|| (isWide() && other.isWide());
}
+ public int requiredRegisters() {
+ return isWide() ? 2 : 1;
+ }
+
public static ValueType fromMemberType(MemberType type) {
switch (type) {
case BOOLEAN:
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 e8e689c..df7deb0 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
@@ -998,24 +998,24 @@
closeCurrentBlock();
}
- public void addIf(If.Type type, int value1, int value2,
+ public void addIf(If.Type type, ValueType operandType, int value1, int value2,
int trueTargetOffset, int falseTargetOffset) {
if (trueTargetOffset == falseTargetOffset) {
addTrivialIf(trueTargetOffset, falseTargetOffset);
} else {
List<Value> values = new ArrayList<>(2);
- values.add(readRegister(value1, ValueType.INT));
- values.add(readRegister(value2, ValueType.INT));
+ values.add(readRegister(value1, operandType));
+ values.add(readRegister(value2, operandType));
If instruction = new If(type, values);
addNonTrivialIf(instruction, trueTargetOffset, falseTargetOffset);
}
}
- public void addIfZero(If.Type type, int value, int trueTargetOffset, int falseTargetOffset) {
+ public void addIfZero(If.Type type, ValueType operandType, int value, int trueTargetOffset, int falseTargetOffset) {
if (trueTargetOffset == falseTargetOffset) {
addTrivialIf(trueTargetOffset, falseTargetOffset);
} else {
- If instruction = new If(type, readRegister(value, ValueType.INT));
+ If instruction = new If(type, readRegister(value, operandType));
addNonTrivialIf(instruction, trueTargetOffset, falseTargetOffset);
}
}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
index 3c102c1..04a2685 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/JarSourceCode.java
@@ -2647,12 +2647,21 @@
assert targets.length == 2;
if (opcode <= Opcodes.IFLE) {
Slot value = state.pop(Type.INT_TYPE);
- builder.addIfZero(ifType(opcode), value.register, targets[0], targets[1]);
+ builder.addIfZero(ifType(opcode), ValueType.INT, value.register, targets[0], targets[1]);
} else {
- Type expectedType = opcode < Opcodes.IF_ACMPEQ ? Type.INT_TYPE : JarState.REFERENCE_TYPE;
+ ValueType valueType;
+ Type expectedType;
+ if (opcode < Opcodes.IF_ACMPEQ) {
+ valueType = ValueType.INT;
+ expectedType = Type.INT_TYPE;
+ } else {
+ valueType = ValueType.OBJECT;
+ expectedType = JarState.REFERENCE_TYPE;
+ }
Slot value2 = state.pop(expectedType);
Slot value1 = state.pop(expectedType);
- builder.addIf(ifType(opcode), value1.register, value2.register, targets[0], targets[1]);
+ builder.addIf(
+ ifType(opcode), valueType, value1.register, value2.register, targets[0], targets[1]);
}
} else {
switch (opcode) {
@@ -2665,7 +2674,7 @@
case Opcodes.IFNONNULL: {
Slot value = state.pop(JarState.REFERENCE_TYPE);
If.Type type = opcode == Opcodes.IFNULL ? If.Type.EQ : If.Type.NE;
- builder.addIfZero(type, value.register, targets[0], targets[1]);
+ builder.addIfZero(type, ValueType.OBJECT, value.register, targets[0], targets[1]);
break;
}
case Opcodes.JSR: {
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 96ccab1..a1c529a 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
@@ -737,10 +737,7 @@
argumentIndex)) {
Value argument = invoke.arguments().get(argumentIndex);
assert invoke.outType().compatible(argument.outType())
- || (!options.outputClassFiles
- && invoke.outType() == ValueType.OBJECT
- && argument.outType().isSingle()
- && argument.isZero());
+ || (!options.outputClassFiles && verifyCompatibleFromDex(invoke, argument));
invoke.outValue().replaceUsers(argument);
invoke.setOutValue(null);
}
@@ -753,6 +750,14 @@
assert code.isConsistentGraph();
}
+ private static boolean verifyCompatibleFromDex(Invoke invoke, Value argument) {
+ ValueType invokeType = invoke.outType();
+ ValueType argumentType = argument.outType();
+ assert argument.isZero();
+ assert (invokeType.isObject() && argumentType.isObjectOrNull())
+ || (invokeType.isSingle() && argumentType.isSingleOrZero());
+ return true;
+ }
/**
* For supporting assert javac adds the static field $assertionsDisabled to all classes which