[LIR] Add support for not instruction.

Also migrates a legacy example regression test.

Bug: b/225838009
Bug: b/167145686
Change-Id: I8dcc30825cdd7edd9fe8c2b419e17602ed17f576
diff --git a/src/main/java/com/android/tools/r8/ir/code/Not.java b/src/main/java/com/android/tools/r8/ir/code/Not.java
index 097ae22..3c6f4c7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Not.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Not.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.lightir.LirBuilder;
 import java.util.function.Function;
 
 public class Not extends Unop {
@@ -105,4 +106,9 @@
     // JVM has no Not instruction, they should be replaced by "Load -1, Xor" before building CF.
     throw new Unreachable();
   }
+
+  @Override
+  public void buildLir(LirBuilder<Value, ?> builder) {
+    builder.addNot(type, source());
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
index bfd5625..2244a37 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -59,6 +59,7 @@
 import com.android.tools.r8.ir.code.NewArrayFilledData;
 import com.android.tools.r8.ir.code.NewInstance;
 import com.android.tools.r8.ir.code.NewUnboxedEnumInstance;
+import com.android.tools.r8.ir.code.Not;
 import com.android.tools.r8.ir.code.NumberConversion;
 import com.android.tools.r8.ir.code.NumberGenerator;
 import com.android.tools.r8.ir.code.NumericType;
@@ -435,6 +436,12 @@
     }
 
     @Override
+    public void onNot(NumericType type, EV value) {
+      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
+      addInstruction(new Not(type, dest, getValue(value)));
+    }
+
+    @Override
     public void onShl(NumericType type, EV left, EV right) {
       Value dest = getOutValueForNextInstruction(valueTypeElement(type));
       addInstruction(new Shl(type, dest, getValue(left), getValue(right)));
@@ -643,7 +650,8 @@
 
     @Override
     public void onInstancePut(DexField field, EV object, EV value) {
-      addInstruction(new InstancePut(field, getValue(object), getValue(value)));
+      addInstruction(
+          InstancePut.createPotentiallyInvalid(field, getValue(object), getValue(value)));
     }
 
     @Override
diff --git a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
index ef0e769..6f56349 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -389,7 +389,7 @@
     return addOneItemInstruction(LirOpcodes.LDC, type);
   }
 
-  public LirBuilder<V, EV> addNeg(NumericType type, V source) {
+  public LirBuilder<V, EV> addNeg(NumericType type, V value) {
     int opcode;
     switch (type) {
       case BYTE:
@@ -410,7 +410,25 @@
       default:
         throw new Unreachable("Unexpected type: " + type);
     }
-    return addOneValueInstruction(opcode, source);
+    return addOneValueInstruction(opcode, value);
+  }
+
+  public LirBuilder<V, EV> addNot(NumericType type, V value) {
+    int opcode;
+    switch (type) {
+      case BYTE:
+      case CHAR:
+      case SHORT:
+      case INT:
+        opcode = LirOpcodes.INOT;
+        break;
+      case LONG:
+        opcode = LirOpcodes.LNOT;
+        break;
+      default:
+        throw new Unreachable("Unexpected type: " + type);
+    }
+    return addOneValueInstruction(opcode, value);
   }
 
   public LirBuilder<V, EV> addDiv(NumericType type, V leftValue, V rightValue) {
diff --git a/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java b/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java
index 19179aa..d7ccc91 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirOpcodes.java
@@ -198,6 +198,8 @@
   int NEWARRAYFILLEDDATA = 215;
   int ITEMBASEDCONSTSTRING = 216;
   int NEWUNBOXEDENUMINSTANCE = 217;
+  int INOT = 218;
+  int LNOT = 219;
 
   static String toString(int opcode) {
     switch (opcode) {
@@ -518,6 +520,10 @@
         return "ITEMBASEDCONSTSTRING";
       case NEWUNBOXEDENUMINSTANCE:
         return "NEWUNBOXEDENUMINSTANCE";
+      case INOT:
+        return "INOT";
+      case LNOT:
+        return "LNOT";
 
       default:
         throw new Unreachable("Unexpected LIR opcode: " + opcode);
diff --git a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
index c19f035..3aebb0e 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -243,6 +243,10 @@
     onInstruction();
   }
 
+  public void onNot(NumericType type, EV value) {
+    onInstruction();
+  }
+
   private void onLogicalBinopInternal(int opcode, LirInstructionView view) {
     EV left = getNextValueOperand(view);
     EV right = getNextValueOperand(view);
@@ -277,7 +281,7 @@
         onXor(NumericType.INT, left, right);
         return;
       case LirOpcodes.LXOR:
-        onXor(NumericType.INT, left, right);
+        onXor(NumericType.LONG, left, right);
         return;
       default:
         throw new Unreachable("Unexpected logical binop: " + opcode);
@@ -1137,6 +1141,13 @@
           onNewUnboxedEnumInstance(type, ordinal);
           return;
         }
+      case LirOpcodes.INOT:
+      case LirOpcodes.LNOT:
+        {
+          EV value = getNextValueOperand(view);
+          onNot(opcode == LirOpcodes.INOT ? NumericType.INT : NumericType.LONG, value);
+          return;
+        }
       default:
         throw new Unimplemented("No dispatch for opcode " + LirOpcodes.toString(opcode));
     }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
index b818d6b..d49c90f 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
@@ -176,6 +176,12 @@
   }
 
   @Override
+  public void onNot(NumericType type, EV value) {
+    appendOutValue();
+    appendValueArguments(value);
+  }
+
+  @Override
   public void onNumberConversion(int opcode, EV value) {
     appendOutValue();
     appendValueArguments(value);
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
index 190ef4b..c8e1bca 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
@@ -27,7 +27,6 @@
     String[] tests = {
       "arithmetic.Arithmetic",
       "inlining.Inlining",
-      "regress_70737019.Test",
       "regress_72361252.Test",
       "regress_110373181.Regress",
       "memberrebinding2.Memberrebinding",
diff --git a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
index 1018d03..da84de5 100644
--- a/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
+++ b/src/test/java/com/android/tools/r8/debug/ExamplesDebugTest.java
@@ -60,11 +60,6 @@
   }
 
   @Test
-  public void testRegress70737019() throws Exception {
-    testDebugging("regress_70737019", "Test");
-  }
-
-  @Test
   public void testRegress72361252() throws Exception {
     testDebugging("regress_72361252", "Test");
   }
diff --git a/src/test/java/com/android/tools/r8/examples/regress_70737019/Regress70737019TestRunner.java b/src/test/java/com/android/tools/r8/examples/regress_70737019/Regress70737019TestRunner.java
new file mode 100644
index 0000000..93bb0d4
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/examples/regress_70737019/Regress70737019TestRunner.java
@@ -0,0 +1,71 @@
+// Copyright (c) 2023, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.examples.regress_70737019;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.examples.ExamplesTestBase;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class Regress70737019TestRunner extends ExamplesTestBase {
+
+  @Parameterized.Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().enableApiLevelsForCf().build();
+  }
+
+  public Regress70737019TestRunner(TestParameters parameters) {
+    super(parameters);
+  }
+
+  @Override
+  public Class<?> getMainClass() {
+    return TestClass.class;
+  }
+
+  @Override
+  public List<Class<?>> getTestClasses() throws Exception {
+    String outerClass = typeName(TestClass.class);
+    return ImmutableList.of(
+        getMainClass(),
+        Class.forName(outerClass + "$1"),
+        Class.forName(outerClass + "$X"),
+        Class.forName(outerClass + "$A"),
+        Class.forName(outerClass + "$B"),
+        Class.forName(outerClass + "$C"));
+  }
+
+  @Override
+  public String getExpected() {
+    return StringUtils.lines(
+        "r  = NaN",
+        "mZ = false",
+        "mI = 1",
+        "mJ = 0",
+        "mF = NaN",
+        "mD = 0.0",
+        "mArray = [[[[[[[[[[1.0775E8]]]]]]]]]]");
+  }
+
+  @Test
+  public void testDesugaring() throws Exception {
+    runTestDesugaring();
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    runTestR8();
+  }
+
+  @Test
+  public void testDebug() throws Exception {
+    runTestDebugComparator();
+  }
+}
diff --git a/src/test/examples/regress_70737019/Test.java b/src/test/java/com/android/tools/r8/examples/regress_70737019/TestClass.java
similarity index 96%
rename from src/test/examples/regress_70737019/Test.java
rename to src/test/java/com/android/tools/r8/examples/regress_70737019/TestClass.java
index 59d498e..27fb29e 100644
--- a/src/test/examples/regress_70737019/Test.java
+++ b/src/test/java/com/android/tools/r8/examples/regress_70737019/TestClass.java
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-package regress_70737019;
+package com.android.tools.r8.examples.regress_70737019;
 
 /**
  * AOSP JFuzz Tester.
@@ -12,7 +12,7 @@
 
 import java.util.Arrays;
 
-public class Test {
+public class TestClass {
 
   private interface X {
     int x();
@@ -63,7 +63,7 @@
     return a && b;
   }
 
-  private Test() {
+  private TestClass() {
     float a = 107750002.0f;
     for (int i0 = 0; i0 < 1; i0++) {
       for (int i1 = 0; i1 < 1; i1++) {
@@ -131,7 +131,7 @@
                   mArray = tmp;
                 }
               }
-              mZ &= ((mI != 820389954) ? mZ : (this instanceof Test));
+              mZ &= ((mI != 820389954) ? mZ : (this instanceof TestClass));
               break;
             }
           }
@@ -168,7 +168,7 @@
           mI %= (~ 1326172655);
           switch (i0) {
             case 0: {
-              mZ |= (true | ((logicalAnd(mZ, (this instanceof Test))) && mZ));
+              mZ |= (true | ((logicalAnd(mZ, (this instanceof TestClass))) && mZ));
               if ((((boolean) new Boolean(true)) || (((boolean) new Boolean((false | (! mZ)))) | (! true)))) {
                 mI /= ((int)(byte)(int) (((mI / mI) >> 265234301) | 188234363));
                 {
@@ -193,7 +193,7 @@
                   }
                 }
               }
-              mZ |= (this instanceof Test);
+              mZ |= (this instanceof TestClass);
               break;
             }
             default: {
@@ -232,7 +232,7 @@
   public static void nop() {}
 
   public static void main(String[] args) {
-    Test t = new Test();
+    TestClass t = new TestClass();
     float r = 1457261414.0f;
     try {
       r = t.testMethod();