Do not use "not" instructions when targeting Dalvik.
MediaTek had a KitKat JIT compiler that did not implement the
"not" instruction. Therefore, generating "not" instructions
can causes crashes for those MediaTek VMs.
R=zerny@google.com
Bug: 73601520
Change-Id: Ica4e0af5ce3ca25e0fc31232fe64c0bc59d223a4
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 43b10f1..0a27017 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
@@ -1517,7 +1517,8 @@
Value in2 = readNumericRegister(right, type);
Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
Instruction instruction;
- if (in2.isConstNumber() &&
+ if (options.canUseNotInstruction() &&
+ in2.isConstNumber() &&
in2.getConstInstruction().asConstNumber().isIntegerNegativeOne(type)) {
instruction = new Not(type, out, in1);
} else {
@@ -1531,7 +1532,7 @@
assert isNonLongIntegerType(type);
Value in1 = readNumericRegister(value, type);
Instruction instruction;
- if (constant == -1) {
+ if (options.canUseNotInstruction() && constant == -1) {
Value out = writeNumericRegister(dest, type, ThrowingInfo.NO_THROW);
instruction = new Not(type, out, in1);
} else {
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 8c3c6ed..902e378 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -479,4 +479,13 @@
public boolean canHaveBoundsCheckEliminationBug() {
return minApiLevel <= AndroidApiLevel.L.getLevel();
}
+
+ // MediaTek JIT compilers for KitKat phones did not implement the not
+ // instruction as it was not generated by DX. Therefore, apps containing
+ // not instructions would crash if the code was JIT compiled. Therefore,
+ // we can only use not instructions if we are targeting Art-based
+ // phones.
+ public boolean canUseNotInstruction() {
+ return minApiLevel >= AndroidApiLevel.L.getLevel();
+ }
}