Optimize AtomicIntegerFieldUpdater.get.

Bug: b/453628974
Change-Id: I99618904e5107056d8a5856dd86443cc606792f4
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelDatabaseHelper.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelDatabaseHelper.java
index 59c3096..6b4cdbe 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelDatabaseHelper.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelDatabaseHelper.java
@@ -577,12 +577,7 @@
             factory.createProto(factory.intType, factory.objectType, factory.longType),
             "getInt"),
         always);
-    apiLevelConsumer.accept(
-        factory.createMethod(
-            factory.sunMiscUnsafeType,
-            factory.createProto(factory.intType, factory.objectType, factory.longType),
-            "getIntVolatile"),
-        always);
+    apiLevelConsumer.accept(factory.sunMiscUnsafeMethods.getIntVolatile, always);
     apiLevelConsumer.accept(
         factory.createMethod(
             factory.sunMiscUnsafeType,
@@ -607,12 +602,7 @@
             factory.createProto(factory.objectType, factory.objectType, factory.longType),
             "getObject"),
         always);
-    apiLevelConsumer.accept(
-        factory.createMethod(
-            factory.sunMiscUnsafeType,
-            factory.createProto(factory.objectType, factory.objectType, factory.longType),
-            "getObjectVolatile"),
-        always);
+    apiLevelConsumer.accept(factory.sunMiscUnsafeMethods.getObjectVolatile, always);
     apiLevelConsumer.accept(
         factory.createMethod(
             factory.sunMiscUnsafeType,
diff --git a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
index cb950bd..e9ca9ab 100644
--- a/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
+++ b/src/main/java/com/android/tools/r8/graph/DexItemFactory.java
@@ -2593,6 +2593,7 @@
   public class AtomicIntUpdaterMethods {
     public final DexMethod newUpdater;
     public final DexMethod compareAndSet;
+    public final DexMethod get;
 
     private AtomicIntUpdaterMethods() {
       newUpdater =
@@ -2607,6 +2608,12 @@
               compareAndSetName,
               booleanDescriptor,
               new DexString[] {objectDescriptor, intDescriptor, intDescriptor});
+      get =
+          createMethod(
+              intFieldUpdaterDescriptor,
+              getName,
+              intDescriptor,
+              new DexString[] {objectDescriptor});
     }
   }
 
@@ -2675,6 +2682,8 @@
     public final DexMethod compareAndSwapInt;
     public final DexMethod compareAndSwapObject;
     public final DexMethod objectFieldOffset;
+    public final DexMethod getObjectVolatile;
+    public final DexMethod getIntVolatile;
 
     private SunMiscUnsafeMethods() {
       this.compareAndSwapInt =
@@ -2689,6 +2698,14 @@
               "compareAndSwapObject");
       this.objectFieldOffset =
           createMethod(sunMiscUnsafeType, createProto(longType, fieldType), "objectFieldOffset");
+      this.getObjectVolatile =
+          createMethod(
+              sunMiscUnsafeType,
+              createProto(objectType, objectType, longType),
+              "getObjectVolatile");
+      this.getIntVolatile =
+          createMethod(
+              sunMiscUnsafeType, createProto(intType, objectType, longType), "getIntVolatile");
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/passes/AtomicFieldUpdaterOptimizer.java b/src/main/java/com/android/tools/r8/ir/conversion/passes/AtomicFieldUpdaterOptimizer.java
index 73863ae..26df724 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/passes/AtomicFieldUpdaterOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/passes/AtomicFieldUpdaterOptimizer.java
@@ -135,7 +135,7 @@
           changed = true;
         }
       } else if (invokedMethod.isIdenticalTo(dexItemFactory.atomicReferenceUpdaterMethods.get)) {
-        if (visitGet(context, invoke)) {
+        if (visitGet(context, invoke, dexItemFactory.sunMiscUnsafeMethods.getObjectVolatile)) {
           changed = true;
         }
       } else if (invokedMethod.isIdenticalTo(dexItemFactory.atomicReferenceUpdaterMethods.set)) {
@@ -153,6 +153,10 @@
             context, invoke, dexItemFactory.sunMiscUnsafeMethods.compareAndSwapInt)) {
           changed = true;
         }
+      } else if (invokedMethod.isIdenticalTo(dexItemFactory.atomicIntUpdaterMethods.get)) {
+        if (visitGet(context, invoke, dexItemFactory.sunMiscUnsafeMethods.getIntVolatile)) {
+          changed = true;
+        }
       } else {
         reportInfo(appView, new Event.CannotOptimize(invoke), Reason.NOT_SUPPORTED);
       }
@@ -190,7 +194,7 @@
   }
 
   /** Returns true if {@code invoke} was rewritten. */
-  private boolean visitGet(OptimizationContext context, InvokeVirtual invoke) {
+  private boolean visitGet(OptimizationContext context, InvokeVirtual invoke, DexMethod target) {
     var resolvedUpdater = resolveUpdater(context, invoke);
     if (resolvedUpdater == null) {
       return false;
@@ -205,7 +209,7 @@
     reportInfo(
         appView,
         new Event.CanOptimize(invoke, resolvedUpdater.isNullable, resolvedHolder.isNullable));
-    rewriteGet(context, invoke, resolvedUpdater, resolvedHolder);
+    rewriteGet(context, invoke, resolvedUpdater, resolvedHolder, target);
     return true;
   }
 
@@ -388,14 +392,15 @@
   }
 
   /**
-   * Rewrites {@code updater.get(holder)} into {@code
-   * SyntheticUnsafeClass.unsafe.getReferenceVolatile(holder, this.offset)}.
+   * Rewrites {@code updater.get(holder)} into {@code SyntheticUnsafeClass.unsafe.<target>(holder,
+   * this.offset)}.
    */
   private void rewriteGet(
       OptimizationContext context,
       InvokeVirtual invoke,
       ResolvedUpdater resolvedUpdater,
-      ResolvedHolder resolvedHolder) {
+      ResolvedHolder resolvedHolder,
+      DexMethod target) {
     var position = invoke.getPosition();
     var instructions = new ArrayList<Instruction>(4);
 
@@ -419,15 +424,9 @@
     insertInstructionsBeforeCurrentInstruction(context.it, instructions);
 
     // Call underlying unsafe method.
-    DexMethod unsafeGetMethod =
-        dexItemFactory.createMethod(
-            dexItemFactory.sunMiscUnsafeType,
-            dexItemFactory.createProto(
-                dexItemFactory.objectType, dexItemFactory.objectType, dexItemFactory.longType),
-            "getObjectVolatile");
     Instruction unsafeGet =
         new InvokeVirtual(
-            unsafeGetMethod,
+            target,
             invoke.outValue(),
             ImmutableList.of(unsafeInstance.outValue(), resolvedHolder.value, offset.outValue()));
     unsafeGet.setPosition(position);
diff --git a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/integer/AtomicFieldUpdaterGetTest.java b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/integer/AtomicFieldUpdaterGetTest.java
index ce1248d..0821557 100644
--- a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/integer/AtomicFieldUpdaterGetTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/integer/AtomicFieldUpdaterGetTest.java
@@ -43,16 +43,29 @@
             diagnostics -> {
               diagnostics.assertInfosMatch(
                   diagnosticMessage(containsString("Can instrument")),
-                  diagnosticMessage(containsString("Cannot optimize")),
-                  diagnosticMessage(containsString("Cannot remove")));
+                  diagnosticMessage(containsString("Can optimize"))
+                  // TODO(b/453628974): The field should be removed once nullability analysis is
+                  //                    more precise.
+                  );
             })
         .inspect(
             inspector -> {
               MethodSubject method = inspector.clazz(testClass).mainMethod();
-              assertThat(
-                  method,
-                  CodeMatchers.invokesMethodWithHolderAndName(
-                      AtomicIntegerFieldUpdater.class, "get"));
+              if (isOptimizationOn()) {
+                assertThat(
+                    method,
+                    CodeMatchers.invokesMethod(
+                        inspector
+                            .getFactory()
+                            .sunMiscUnsafeMethods
+                            .getIntVolatile
+                            .asMethodReference()));
+              } else {
+                assertThat(
+                    method,
+                    CodeMatchers.invokesMethodWithHolderAndName(
+                        AtomicIntegerFieldUpdater.class, "get"));
+              }
             })
         .run(parameters.getRuntime(), testClass)
         .assertSuccessWithOutputLines("123");
diff --git a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterGetTest.java b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterGetTest.java
index b437870..d65f072 100644
--- a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterGetTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterGetTest.java
@@ -55,8 +55,12 @@
               if (isOptimizationOn()) {
                 assertThat(
                     method,
-                    CodeMatchers.invokesMethodWithHolderAndName(
-                        "sun.misc.Unsafe", "getObjectVolatile"));
+                    CodeMatchers.invokesMethod(
+                        inspector
+                            .getFactory()
+                            .sunMiscUnsafeMethods
+                            .getObjectVolatile
+                            .asMethodReference()));
               } else {
                 assertThat(
                     method,
diff --git a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterNullableHolderTest.java b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterNullableHolderTest.java
index 7b368a4..3713b7b 100644
--- a/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterNullableHolderTest.java
+++ b/src/test/java/com/android/tools/r8/optimize/atomicfieldupdater/reference/AtomicFieldUpdaterNullableHolderTest.java
@@ -54,8 +54,12 @@
               if (isOptimizationOn()) {
                 assertThat(
                     method,
-                    CodeMatchers.invokesMethodWithHolderAndName(
-                        "sun.misc.Unsafe", "getObjectVolatile"));
+                    CodeMatchers.invokesMethod(
+                        inspector
+                            .getFactory()
+                            .sunMiscUnsafeMethods
+                            .getObjectVolatile
+                            .asMethodReference()));
               } else {
                 assertThat(
                     method,