Reland "Differentiate compiler synthesized ConstClass/CheckCast"

This reverts commit 10b104ffe3b77d3e289ac828ca8281da5d5c5e90.

Bug: 200933020
Change-Id: I8f7d19a042d67367ccd4c25502534e69af24b0dc
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
index 2220c7d..9e198e4 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfCheckCast.java
@@ -30,9 +30,19 @@
 public class CfCheckCast extends CfInstruction implements CfTypeInstruction {
 
   private final DexType type;
+  private final boolean ignoreCompatRules;
 
   public CfCheckCast(DexType type) {
+    this(type, false);
+  }
+
+  public CfCheckCast(DexType type, boolean ignoreCompatRules) {
     this.type = type;
+    this.ignoreCompatRules = ignoreCompatRules;
+  }
+
+  public boolean ignoreCompatRules() {
+    return ignoreCompatRules;
   }
 
   @Override
@@ -52,7 +62,7 @@
 
   @Override
   public CfInstruction withType(DexType newType) {
-    return new CfCheckCast(newType);
+    return new CfCheckCast(newType, ignoreCompatRules());
   }
 
   @Override
@@ -88,7 +98,7 @@
   @Override
   void internalRegisterUse(
       UseRegistry<?> registry, DexClassAndMethod context, ListIterator<CfInstruction> iterator) {
-    registry.registerCheckCast(type);
+    registry.registerCheckCast(type, ignoreCompatRules());
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
index 78fbcd2..07cb6d2 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfConstClass.java
@@ -30,9 +30,19 @@
 public class CfConstClass extends CfInstruction implements CfTypeInstruction {
 
   private final DexType type;
+  private final boolean ignoreCompatRules;
 
   public CfConstClass(DexType type) {
+    this(type, false);
+  }
+
+  public CfConstClass(DexType type, boolean ignoreCompatRules) {
     this.type = type;
+    this.ignoreCompatRules = ignoreCompatRules;
+  }
+
+  public boolean ignoreCompatRules() {
+    return ignoreCompatRules;
   }
 
   @Override
@@ -119,7 +129,7 @@
   @Override
   void internalRegisterUse(
       UseRegistry<?> registry, DexClassAndMethod context, ListIterator<CfInstruction> iterator) {
-    registry.registerConstClass(type, iterator);
+    registry.registerConstClass(type, iterator, ignoreCompatRules());
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfSafeCheckCast.java b/src/main/java/com/android/tools/r8/cf/code/CfSafeCheckCast.java
index 9fe64c6..f4e70ff 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfSafeCheckCast.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfSafeCheckCast.java
@@ -14,7 +14,7 @@
 public class CfSafeCheckCast extends CfCheckCast {
 
   public CfSafeCheckCast(DexType type) {
-    super(type);
+    super(type, true);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/code/CheckCast.java b/src/main/java/com/android/tools/r8/code/CheckCast.java
index cb21b8c..74a5f91 100644
--- a/src/main/java/com/android/tools/r8/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/code/CheckCast.java
@@ -21,12 +21,16 @@
   public static final String NAME = "CheckCast";
   public static final String SMALI_NAME = "check-cast";
 
+  private final boolean ignoreCompatRules;
+
   CheckCast(int high, BytecodeStream stream, OffsetToObjectMapping mapping) {
     super(high, stream, mapping.getTypeMap());
+    this.ignoreCompatRules = false;
   }
 
-  public CheckCast(int valueRegister, DexType type) {
+  public CheckCast(int valueRegister, DexType type, boolean ignoreCompatRules) {
     super(valueRegister, type);
+    this.ignoreCompatRules = ignoreCompatRules;
   }
 
   @Override
@@ -50,6 +54,11 @@
   }
 
   @Override
+  public boolean ignoreCompatRules() {
+    return ignoreCompatRules;
+  }
+
+  @Override
   public void collectIndexedItems(
       IndexedItemCollection indexedItems,
       ProgramMethod context,
@@ -83,7 +92,7 @@
 
   @Override
   public void registerUse(UseRegistry<?> registry) {
-    registry.registerCheckCast(getType());
+    registry.registerCheckCast(getType(), ignoreCompatRules());
   }
 
   public DexType getType() {
diff --git a/src/main/java/com/android/tools/r8/code/ConstClass.java b/src/main/java/com/android/tools/r8/code/ConstClass.java
index f57556a..88b35e1 100644
--- a/src/main/java/com/android/tools/r8/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/code/ConstClass.java
@@ -21,12 +21,16 @@
   public static final String NAME = "ConstClass";
   public static final String SMALI_NAME = "const-class";
 
+  private final boolean ignoreCompatRules;
+
   ConstClass(int high, BytecodeStream stream, OffsetToObjectMapping mapping) {
     super(high, stream, mapping.getTypeMap());
+    this.ignoreCompatRules = false;
   }
 
-  public ConstClass(int dest, DexType type) {
+  public ConstClass(int dest, DexType type, boolean ignoreCompatRules) {
     super(dest, type);
+    this.ignoreCompatRules = ignoreCompatRules;
   }
 
   @Override
@@ -35,6 +39,11 @@
   }
 
   @Override
+  public boolean ignoreCompatRules() {
+    return ignoreCompatRules;
+  }
+
+  @Override
   public String getName() {
     return NAME;
   }
@@ -73,7 +82,7 @@
 
   @Override
   public void registerUse(UseRegistry<?> registry) {
-    registry.registerConstClass(getType(), null);
+    registry.registerConstClass(getType(), null, ignoreCompatRules());
   }
 
   public DexType getType() {
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index 96e754e..5a10577 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -243,6 +243,10 @@
     return 0;
   }
 
+  public boolean ignoreCompatRules() {
+    return false;
+  }
+
   static String formatOffset(int offset) {
     return StringUtils.hexString(offset, 2);
   }
diff --git a/src/main/java/com/android/tools/r8/code/SafeCheckCast.java b/src/main/java/com/android/tools/r8/code/SafeCheckCast.java
index 7fff773..8f19396 100644
--- a/src/main/java/com/android/tools/r8/code/SafeCheckCast.java
+++ b/src/main/java/com/android/tools/r8/code/SafeCheckCast.java
@@ -16,7 +16,7 @@
   }
 
   public SafeCheckCast(int valueRegister, DexType type) {
-    super(valueRegister, type);
+    super(valueRegister, type, true);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/graph/UseRegistry.java b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
index 85241b8..c3912ca 100644
--- a/src/main/java/com/android/tools/r8/graph/UseRegistry.java
+++ b/src/main/java/com/android/tools/r8/graph/UseRegistry.java
@@ -121,16 +121,18 @@
   }
 
   public void registerConstClass(
-      DexType type, ListIterator<? extends CfOrDexInstruction> iterator) {
+      DexType type,
+      ListIterator<? extends CfOrDexInstruction> iterator,
+      boolean ignoreCompatRules) {
     registerTypeReference(type);
   }
 
-  public void registerCheckCast(DexType type) {
+  public void registerCheckCast(DexType type, boolean ignoreCompatRules) {
     registerTypeReference(type);
   }
 
   public void registerSafeCheckCast(DexType type) {
-    registerCheckCast(type);
+    registerCheckCast(type, true);
   }
 
   public void registerExceptionGuard(DexType guard) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java
index 5a96b56..253665f 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/ProtoEnqueuerUseRegistry.java
@@ -40,20 +40,23 @@
   }
 
   /**
-   * Unlike {@link DefaultEnqueuerUseRegistry#registerConstClass(DexType, ListIterator)}, this
-   * method does not trace any const-class instructions in every implementation of dynamicMethod().
+   * Unlike {@link DefaultEnqueuerUseRegistry#registerConstClass(DexType, ListIterator, boolean)},
+   * this method does not trace any const-class instructions in every implementation of
+   * dynamicMethod().
    *
    * <p>The const-class instructions that remain after the proto schema has been optimized will be
    * traced manually by {@link ProtoEnqueuerExtension#tracePendingInstructionsInDynamicMethods}.
    */
   @Override
   public void registerConstClass(
-      DexType type, ListIterator<? extends CfOrDexInstruction> iterator) {
+      DexType type,
+      ListIterator<? extends CfOrDexInstruction> iterator,
+      boolean ignoreCompatRules) {
     if (references.isDynamicMethod(getContextMethod())) {
       enqueuer.addDeadProtoTypeCandidate(type);
       return;
     }
-    super.registerConstClass(type, iterator);
+    super.registerConstClass(type, iterator, ignoreCompatRules);
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
index e7d953a..66747a7 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/proto/schema/ProtoEnqueuerExtension.java
@@ -497,7 +497,7 @@
                   object.asProtoObjectFromStaticGet().getField(), dynamicMethod);
             } else if (object.isProtoTypeObject()) {
               worklist.enqueueTraceConstClassAction(
-                  object.asProtoTypeObject().getType(), dynamicMethod);
+                  object.asProtoTypeObject().getType(), dynamicMethod, false);
             }
           }
         }
diff --git a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
index b5e4027..764167c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
@@ -30,14 +30,20 @@
 public class CheckCast extends Instruction {
 
   private final DexType type;
+  private final boolean ignoreCompatRules;
 
   // A CheckCast dex instruction takes only one register containing a value and changes
   // the associated type information for that value. In the IR we let the CheckCast
   // instruction define a new value. During register allocation we then need to arrange it
   // so that the source and destination are assigned the same register.
   public CheckCast(Value dest, Value value, DexType type) {
+    this(dest, value, type, false);
+  }
+
+  public CheckCast(Value dest, Value value, DexType type, boolean ignoreCompatRules) {
     super(dest, value);
     this.type = type;
+    this.ignoreCompatRules = ignoreCompatRules;
   }
 
   public static Builder builder() {
@@ -66,6 +72,11 @@
   }
 
   @Override
+  public boolean ignoreCompatRules() {
+    return ignoreCompatRules;
+  }
+
+  @Override
   public int opcode() {
     return Opcodes.CHECK_CAST;
   }
@@ -107,7 +118,7 @@
   }
 
   com.android.tools.r8.code.CheckCast createCheckCast(int register) {
-    return new com.android.tools.r8.code.CheckCast(register, getType());
+    return new com.android.tools.r8.code.CheckCast(register, getType(), ignoreCompatRules());
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index 0fa4236..93cefd2 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
@@ -26,10 +26,16 @@
 public class ConstClass extends ConstInstruction {
 
   private final DexType clazz;
+  private final boolean ignoreCompatRules;
 
   public ConstClass(Value dest, DexType clazz) {
+    this(dest, clazz, false);
+  }
+
+  public ConstClass(Value dest, DexType clazz, boolean ignoreCompatRules) {
     super(dest);
     this.clazz = clazz;
+    this.ignoreCompatRules = ignoreCompatRules;
   }
 
   public static Builder builder() {
@@ -72,7 +78,12 @@
   @Override
   public void buildDex(DexBuilder builder) {
     int dest = builder.allocatedRegister(dest(), getNumber());
-    builder.add(this, new com.android.tools.r8.code.ConstClass(dest, clazz));
+    builder.add(this, new com.android.tools.r8.code.ConstClass(dest, clazz, ignoreCompatRules()));
+  }
+
+  @Override
+  public boolean ignoreCompatRules() {
+    return ignoreCompatRules;
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Instruction.java b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
index 85ac375..9bccbfc 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Instruction.java
@@ -120,6 +120,10 @@
     }
   }
 
+  public boolean ignoreCompatRules() {
+    return false;
+  }
+
   public boolean hasInValueWithLocalInfo() {
     return hasInValueThatMatches(Value::hasLocalInfo);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
index d012cd6..c7b07d3 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/LensCodeRewriter.java
@@ -563,7 +563,9 @@
               CheckCast checkCast = current.asCheckCast();
               new InstructionReplacer(code, current, iterator, affectedPhis)
                   .replaceInstructionIfTypeChanged(
-                      checkCast.getType(), (t, v) -> new CheckCast(v, checkCast.object(), t));
+                      checkCast.getType(),
+                      (t, v) ->
+                          new CheckCast(v, checkCast.object(), t, checkCast.ignoreCompatRules()));
             }
             break;
 
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
index 09319b6..0c1ee6e 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/records/RecordDesugaring.java
@@ -391,7 +391,7 @@
     assert recordInvokeDynamic.getRecordClass().lookupProgramMethod(getFieldsAsObjects) != null;
     ArrayList<CfInstruction> instructions = new ArrayList<>();
     instructions.add(new CfInvoke(Opcodes.INVOKESPECIAL, getFieldsAsObjects, false));
-    instructions.add(new CfConstClass(recordInvokeDynamic.getRecordClass().type));
+    instructions.add(new CfConstClass(recordInvokeDynamic.getRecordClass().type, true));
     instructions.add(new CfConstString(recordInvokeDynamic.getFieldNames()));
     ProgramMethod programMethod =
         synthesizeRecordHelper(
diff --git a/src/main/java/com/android/tools/r8/ir/synthetic/RecordCfCodeProvider.java b/src/main/java/com/android/tools/r8/ir/synthetic/RecordCfCodeProvider.java
index ce66391..e9fc30b 100644
--- a/src/main/java/com/android/tools/r8/ir/synthetic/RecordCfCodeProvider.java
+++ b/src/main/java/com/android/tools/r8/ir/synthetic/RecordCfCodeProvider.java
@@ -158,7 +158,7 @@
       instructions.add(new CfLoad(recordType, 0));
       instructions.add(new CfInvoke(Opcodes.INVOKESPECIAL, getFieldsAsObjects, false));
       instructions.add(new CfLoad(objectType, 1));
-      instructions.add(new CfCheckCast(getHolder()));
+      instructions.add(new CfCheckCast(getHolder(), true));
       instructions.add(new CfInvoke(Opcodes.INVOKESPECIAL, getFieldsAsObjects, false));
       instructions.add(
           new CfInvoke(
diff --git a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
index 2287be5..33288f7 100644
--- a/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
+++ b/src/main/java/com/android/tools/r8/shaking/DefaultEnqueuerUseRegistry.java
@@ -139,13 +139,15 @@
 
   @Override
   public void registerConstClass(
-      DexType type, ListIterator<? extends CfOrDexInstruction> iterator) {
-    enqueuer.traceConstClass(type, getContext(), iterator);
+      DexType type,
+      ListIterator<? extends CfOrDexInstruction> iterator,
+      boolean ignoreCompatRules) {
+    enqueuer.traceConstClass(type, getContext(), iterator, ignoreCompatRules);
   }
 
   @Override
-  public void registerCheckCast(DexType type) {
-    enqueuer.traceCheckCast(type, getContext());
+  public void registerCheckCast(DexType type, boolean ignoreCompatRules) {
+    enqueuer.traceCheckCast(type, getContext(), ignoreCompatRules);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
index b4fef63..ec6c061 100644
--- a/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
+++ b/src/main/java/com/android/tools/r8/shaking/Enqueuer.java
@@ -1034,22 +1034,23 @@
     }
   }
 
-  void traceCheckCast(DexType type, ProgramMethod currentMethod) {
+  void traceCheckCast(DexType type, ProgramMethod currentMethod, boolean ignoreCompatRules) {
     checkCastAnalyses.forEach(analysis -> analysis.traceCheckCast(type, currentMethod));
-    traceConstClassOrCheckCast(type, currentMethod);
+    internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
   }
 
   void traceSafeCheckCast(DexType type, ProgramMethod currentMethod) {
     checkCastAnalyses.forEach(analysis -> analysis.traceSafeCheckCast(type, currentMethod));
-    traceCompilerSynthesizedConstClassOrCheckCast(type, currentMethod);
+    internalTraceConstClassOrCheckCast(type, currentMethod, true);
   }
 
   void traceConstClass(
       DexType type,
       ProgramMethod currentMethod,
-      ListIterator<? extends CfOrDexInstruction> iterator) {
+      ListIterator<? extends CfOrDexInstruction> iterator,
+      boolean ignoreCompatRules) {
     handleLockCandidate(type, currentMethod, iterator);
-    traceConstClassOrCheckCast(type, currentMethod);
+    internalTraceConstClassOrCheckCast(type, currentMethod, ignoreCompatRules);
   }
 
   private void handleLockCandidate(
@@ -1103,22 +1104,10 @@
     return result;
   }
 
-  private void traceConstClassOrCheckCast(DexType type, ProgramMethod currentMethod) {
-    internalTraceConstClassOrCheckCast(type, currentMethod, false);
-  }
-
-  // TODO(b/190487539): Currently only used by traceSafeCheckCast(), but should also be used to
-  //  ensure we don't trigger compat behavior for const-class instructions synthesized for
-  //  synchronized methods.
-  private void traceCompilerSynthesizedConstClassOrCheckCast(
-      DexType type, ProgramMethod currentMethod) {
-    internalTraceConstClassOrCheckCast(type, currentMethod, true);
-  }
-
   private void internalTraceConstClassOrCheckCast(
-      DexType type, ProgramMethod currentMethod, boolean isCompilerSynthesized) {
+      DexType type, ProgramMethod currentMethod, boolean ignoreCompatRules) {
     traceTypeReference(type, currentMethod);
-    if (!forceProguardCompatibility || isCompilerSynthesized) {
+    if (!forceProguardCompatibility || ignoreCompatRules) {
       return;
     }
     DexType baseType = type.toBaseType(appView.dexItemFactory());
diff --git a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
index ad3d4d1..1f4bc35 100644
--- a/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
+++ b/src/main/java/com/android/tools/r8/shaking/EnqueuerWorklist.java
@@ -227,15 +227,17 @@
     private final DexType type;
     // TODO(b/175854431): Avoid pushing context on worklist.
     private final ProgramMethod context;
+    private final boolean ignoreCompatRules;
 
-    TraceConstClassAction(DexType type, ProgramMethod context) {
+    TraceConstClassAction(DexType type, ProgramMethod context, boolean ignoreCompatRules) {
       this.type = type;
       this.context = context;
+      this.ignoreCompatRules = ignoreCompatRules;
     }
 
     @Override
     public void run(Enqueuer enqueuer) {
-      enqueuer.traceConstClass(type, context, null);
+      enqueuer.traceConstClass(type, context, null, ignoreCompatRules);
     }
   }
 
@@ -356,7 +358,8 @@
 
   public abstract void enqueueTraceCodeAction(ProgramMethod method);
 
-  public abstract void enqueueTraceConstClassAction(DexType type, ProgramMethod context);
+  public abstract void enqueueTraceConstClassAction(
+      DexType type, ProgramMethod context, boolean ignoreCompatRules);
 
   public abstract void enqueueTraceInvokeDirectAction(
       DexMethod invokedMethod, ProgramMethod context);
@@ -464,8 +467,9 @@
     }
 
     @Override
-    public void enqueueTraceConstClassAction(DexType type, ProgramMethod context) {
-      queue.add(new TraceConstClassAction(type, context));
+    public void enqueueTraceConstClassAction(
+        DexType type, ProgramMethod context, boolean ignoreCompatRules) {
+      queue.add(new TraceConstClassAction(type, context, ignoreCompatRules));
     }
 
     @Override
@@ -580,26 +584,23 @@
     }
 
     @Override
-    public void enqueueTraceConstClassAction(DexType type, ProgramMethod context) {
-
+    public void enqueueTraceConstClassAction(
+        DexType type, ProgramMethod context, boolean ignoreCompatRules) {
       throw attemptToEnqueue();
     }
 
     @Override
     public void enqueueTraceInvokeDirectAction(DexMethod invokedMethod, ProgramMethod context) {
-
       throw attemptToEnqueue();
     }
 
     @Override
     public void enqueueTraceNewInstanceAction(DexType type, ProgramMethod context) {
-
       throw attemptToEnqueue();
     }
 
     @Override
     public void enqueueTraceStaticFieldRead(DexField field, ProgramMethod context) {
-
       throw attemptToEnqueue();
     }
   }
diff --git a/src/test/java/com/android/tools/r8/desugar/records/RecordShrinkFieldTest.java b/src/test/java/com/android/tools/r8/desugar/records/RecordShrinkFieldTest.java
index d46e947..7b653ed 100644
--- a/src/test/java/com/android/tools/r8/desugar/records/RecordShrinkFieldTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/records/RecordShrinkFieldTest.java
@@ -67,6 +67,22 @@
   }
 
   @Test
+  public void testR8Compat() throws Exception {
+    testForR8Compat(parameters.getBackend())
+        .addProgramClassFileData(PROGRAM_DATA)
+        .setMinApi(parameters.getApiLevel())
+        .addKeepMainRule(MAIN_TYPE)
+        .addKeepRules(
+            "-keepclassmembers,allowshrinking,allowoptimization class"
+                + " records.RecordShrinkField$Person { <fields>; }")
+        .addOptionsModification(TestingOptions::allowExperimentClassFileVersion)
+        .compile()
+        .inspect(this::assertSingleField)
+        .run(parameters.getRuntime(), MAIN_TYPE)
+        .assertSuccessWithOutput(EXPECTED_RESULT_R8);
+  }
+
+  @Test
   public void testR8CfThenDex() throws Exception {
     Path desugared =
         testForR8(Backend.CF)