Logic for rewriting instance initializer info with a lens

Change-Id: Iea6881ddae03620d5a41deff8d37ef45190910fb
Bug: 150193407
diff --git a/src/main/java/com/android/tools/r8/graph/EnumValueInfoMapCollection.java b/src/main/java/com/android/tools/r8/graph/EnumValueInfoMapCollection.java
index c6a9a8b..4fd96f7 100644
--- a/src/main/java/com/android/tools/r8/graph/EnumValueInfoMapCollection.java
+++ b/src/main/java/com/android/tools/r8/graph/EnumValueInfoMapCollection.java
@@ -114,6 +114,10 @@
       this.ordinal = ordinal;
     }
 
+    public int convertToInt() {
+      return ordinal + 1;
+    }
+
     EnumValueInfo rewrittenWithLens(GraphLense lens) {
       DexType newType = lens.lookupType(type);
       if (type == newType) {
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/AbstractFieldSet.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/AbstractFieldSet.java
index 90320b7..c6e42b6 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/AbstractFieldSet.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/AbstractFieldSet.java
@@ -4,7 +4,9 @@
 
 package com.android.tools.r8.ir.analysis.fieldvalueanalysis;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.GraphLense;
 
 /**
  * Implements a lifted subset lattice for fields.
@@ -42,6 +44,8 @@
 
   public abstract boolean contains(DexEncodedField field);
 
+  public abstract boolean isEmpty();
+
   public boolean isBottom() {
     return false;
   }
@@ -65,4 +69,6 @@
   public final boolean strictlyLessThan(AbstractFieldSet other) {
     return lessThanOrEqual(other) && !equals(other);
   }
+
+  public abstract AbstractFieldSet rewrittenWithLens(AppView<?> appView, GraphLense lens);
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java
index bc13aa1..a2a932c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/ConcreteMutableFieldSet.java
@@ -4,7 +4,9 @@
 
 package com.android.tools.r8.ir.analysis.fieldvalueanalysis;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.SetUtils;
 import com.google.common.collect.Sets;
@@ -65,6 +67,26 @@
   }
 
   @Override
+  public AbstractFieldSet rewrittenWithLens(AppView<?> appView, GraphLense lens) {
+    assert !isEmpty();
+    ConcreteMutableFieldSet rewrittenSet = new ConcreteMutableFieldSet();
+    for (DexEncodedField field : fields) {
+      DexEncodedField rewrittenField = appView.definitionFor(lens.lookupField(field.field));
+      if (rewrittenField == null) {
+        assert false;
+        continue;
+      }
+      rewrittenSet.add(field);
+    }
+    return rewrittenSet;
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return fields.isEmpty();
+  }
+
+  @Override
   public int size() {
     return fields.size();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/EmptyFieldSet.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/EmptyFieldSet.java
index c50ded8..73559f3 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/EmptyFieldSet.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/EmptyFieldSet.java
@@ -4,7 +4,9 @@
 
 package com.android.tools.r8.ir.analysis.fieldvalueanalysis;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.GraphLense;
 
 public class EmptyFieldSet extends AbstractFieldSet implements KnownFieldSet {
 
@@ -37,6 +39,16 @@
   }
 
   @Override
+  public AbstractFieldSet rewrittenWithLens(AppView<?> appView, GraphLense lens) {
+    return this;
+  }
+
+  @Override
+  public boolean isEmpty() {
+    return true;
+  }
+
+  @Override
   public int size() {
     return 0;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/UnknownFieldSet.java b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/UnknownFieldSet.java
index 9df87cc..f083438 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/UnknownFieldSet.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/fieldvalueanalysis/UnknownFieldSet.java
@@ -4,7 +4,9 @@
 
 package com.android.tools.r8.ir.analysis.fieldvalueanalysis;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.GraphLense;
 
 public class UnknownFieldSet extends AbstractFieldSet {
 
@@ -22,7 +24,17 @@
   }
 
   @Override
+  public boolean isEmpty() {
+    return false;
+  }
+
+  @Override
   public boolean isTop() {
     return true;
   }
+
+  @Override
+  public AbstractFieldSet rewrittenWithLens(AppView<?> appView, GraphLense lens) {
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
index 5371255..83a0525 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/AbstractValue.java
@@ -4,6 +4,10 @@
 
 package com.android.tools.r8.ir.analysis.value;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
 public abstract class AbstractValue {
 
   public abstract boolean isNonTrivial();
@@ -85,6 +89,9 @@
     return UnknownValue.getInstance();
   }
 
+  public abstract AbstractValue rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens);
+
   @Override
   public abstract boolean equals(Object o);
 
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/BottomValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/BottomValue.java
index ca376e7..f5b27f7 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/BottomValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/BottomValue.java
@@ -4,6 +4,10 @@
 
 package com.android.tools.r8.ir.analysis.value;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
 public class BottomValue extends AbstractValue {
 
   private static final BottomValue INSTANCE = new BottomValue();
@@ -20,6 +24,11 @@
   }
 
   @Override
+  public AbstractValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return this;
+  }
+
+  @Override
   public boolean isNonTrivial() {
     return true;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
index a6bf499..6261b05 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleConstClassValue.java
@@ -13,12 +13,14 @@
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.ConstClass;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
 import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class SingleConstClassValue extends SingleValue {
 
@@ -88,4 +90,10 @@
     assert baseType.isPrimitiveType();
     return true;
   }
+
+  @Override
+  public SingleValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    assert lens.lookupType(type) == type;
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleEnumValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleEnumValue.java
index 313f977..4beb525 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleEnumValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleEnumValue.java
@@ -4,7 +4,11 @@
 
 package com.android.tools.r8.ir.analysis.value;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection.EnumValueInfoMap;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class SingleEnumValue extends SingleFieldValue {
 
@@ -27,4 +31,18 @@
   public String toString() {
     return "SingleEnumValue(" + getField().toSourceString() + ")";
   }
+
+  @Override
+  public SingleValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    DexField field = getField();
+    EnumValueInfoMap unboxedEnumInfo = appView.unboxedEnums().getEnumValueInfoMap(field.type);
+    if (unboxedEnumInfo != null) {
+      // Return the ordinal of the unboxed enum.
+      assert unboxedEnumInfo.hasEnumValueInfo(field);
+      return appView
+          .abstractValueFactory()
+          .createSingleNumberValue(unboxedEnumInfo.getEnumValueInfo(field).convertToInt());
+    }
+    return appView.abstractValueFactory().createSingleEnumValue(lens.lookupField(field));
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
index 0adfe65..c549f6c 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleFieldValue.java
@@ -12,12 +12,14 @@
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.StaticGet;
 import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
 import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class SingleFieldValue extends SingleValue {
 
@@ -72,4 +74,10 @@
     return isMemberVisibleFromOriginalContext(
         appView, context, encodedField.field.holder, encodedField.accessFlags);
   }
+
+  @Override
+  public SingleValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    assert !appView.unboxedEnums().containsEnum(field.holder);
+    return appView.abstractValueFactory().createSingleFieldValue(lens.lookupField(field));
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
index 4a5ad60..df49b54 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleNumberValue.java
@@ -8,12 +8,14 @@
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.ConstNumber;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
 import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class SingleNumberValue extends SingleValue {
 
@@ -79,4 +81,9 @@
   public boolean isMaterializableInContext(AppView<?> appView, DexType context) {
     return true;
   }
+
+  @Override
+  public SingleValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
index 417fe19..9564584 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleStringValue.java
@@ -12,6 +12,7 @@
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
 import com.android.tools.r8.ir.code.ConstString;
@@ -19,6 +20,7 @@
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
 import com.android.tools.r8.ir.code.Value;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class SingleStringValue extends SingleValue {
 
@@ -84,4 +86,9 @@
   public boolean isMaterializableInContext(AppView<?> appView, DexType context) {
     return true;
   }
+
+  @Override
+  public SingleValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
index c7b249f..6bb2942 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/SingleValue.java
@@ -7,10 +7,12 @@
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.TypeAndLocalInfoSupplier;
 import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfo;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public abstract class SingleValue extends AbstractValue implements InstanceFieldInitializationInfo {
 
@@ -37,4 +39,8 @@
       AppView<? extends AppInfoWithSubtyping> appView, IRCode code, TypeAndLocalInfoSupplier info);
 
   public abstract boolean isMaterializableInContext(AppView<?> appView, DexType context);
+
+  @Override
+  public abstract SingleValue rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens);
 }
diff --git a/src/main/java/com/android/tools/r8/ir/analysis/value/UnknownValue.java b/src/main/java/com/android/tools/r8/ir/analysis/value/UnknownValue.java
index 216ea99..2b4f841 100644
--- a/src/main/java/com/android/tools/r8/ir/analysis/value/UnknownValue.java
+++ b/src/main/java/com/android/tools/r8/ir/analysis/value/UnknownValue.java
@@ -4,6 +4,10 @@
 
 package com.android.tools.r8.ir.analysis.value;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
 public class UnknownValue extends AbstractValue {
 
   private static final UnknownValue INSTANCE = new UnknownValue();
@@ -25,6 +29,11 @@
   }
 
   @Override
+  public AbstractValue rewrittenWithLens(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return this;
+  }
+
+  @Override
   public boolean equals(Object o) {
     return this == o;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
index 9dd958f..038bc33 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRConverter.java
@@ -700,7 +700,7 @@
     }
     if (enumUnboxer != null) {
       enumUnboxer.finishAnalysis();
-      enumUnboxer.unboxEnums(postMethodProcessorBuilder);
+      enumUnboxer.unboxEnums(postMethodProcessorBuilder, executorService, feedback);
     }
     timing.begin("IR conversion phase 2");
     graphLenseForIR = appView.graphLense();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
index 1aa0955..e96b211 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxer.java
@@ -38,6 +38,10 @@
 import com.android.tools.r8.ir.conversion.IRConverter;
 import com.android.tools.r8.ir.conversion.PostMethodProcessor;
 import com.android.tools.r8.ir.conversion.PostOptimization;
+import com.android.tools.r8.ir.optimize.info.FieldOptimizationInfo;
+import com.android.tools.r8.ir.optimize.info.MethodOptimizationInfo;
+import com.android.tools.r8.ir.optimize.info.OptimizationFeedback.OptimizationInfoFixer;
+import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackDelayed;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.BooleanUtils;
 import com.android.tools.r8.utils.Reporter;
@@ -227,7 +231,11 @@
     return Reason.ELIGIBLE;
   }
 
-  public void unboxEnums(PostMethodProcessor.Builder postBuilder) {
+  public void unboxEnums(
+      PostMethodProcessor.Builder postBuilder,
+      ExecutorService executorService,
+      OptimizationFeedbackDelayed feedback)
+      throws ExecutionException {
     // At this point the enumsToUnbox are no longer candidates, they will all be unboxed.
     if (enumsUnboxingCandidates.isEmpty()) {
       return;
@@ -242,6 +250,37 @@
           appView
               .appInfo()
               .rewrittenWithLens(appView.appInfo().app().asDirect(), enumUnboxingLens));
+
+      // Update optimization info.
+      feedback.fixupOptimizationInfos(
+          appView,
+          executorService,
+          new OptimizationInfoFixer() {
+            @Override
+            public void fixup(DexEncodedField field) {
+              FieldOptimizationInfo optimizationInfo = field.getOptimizationInfo();
+              if (optimizationInfo.isMutableFieldOptimizationInfo()) {
+                optimizationInfo
+                    .asMutableFieldOptimizationInfo()
+                    .fixupAbstractValue(appView, appView.graphLense());
+              } else {
+                assert optimizationInfo.isDefaultFieldOptimizationInfo();
+              }
+            }
+
+            @Override
+            public void fixup(DexEncodedMethod method) {
+              MethodOptimizationInfo optimizationInfo = method.getOptimizationInfo();
+              if (optimizationInfo.isUpdatableMethodOptimizationInfo()) {
+                optimizationInfo
+                    .asUpdatableMethodOptimizationInfo()
+                    .fixupAbstractReturnValue(appView, appView.graphLense())
+                    .fixupInstanceInitializerInfo(appView, appView.graphLense());
+              } else {
+                assert optimizationInfo.isDefaultMethodOptimizationInfo();
+              }
+            }
+          });
     }
     postBuilder.put(this);
     postBuilder.mapDexEncodedMethods(appView);
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
index c05f41b..cbd3824 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/enums/EnumUnboxingRewriter.java
@@ -121,7 +121,7 @@
           EnumValueInfo enumValueInfo = enumValueInfoMap.getEnumValueInfo(staticGet.getField());
           assert enumValueInfo != null
               : "Invalid read to " + staticGet.getField().name + ", error during enum analysis";
-          instruction = new ConstNumber(staticGet.outValue(), enumValueInfo.ordinal + 1);
+          instruction = new ConstNumber(staticGet.outValue(), enumValueInfo.convertToInt());
           staticGet
               .outValue()
               .setTypeLattice(PrimitiveTypeLatticeElement.fromNumericType(NumericType.INT));
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
index 33c7b2a..0626a7b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/MutableFieldOptimizationInfo.java
@@ -7,10 +7,12 @@
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
 import com.android.tools.r8.ir.analysis.value.UnknownValue;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.function.Function;
 
 /**
@@ -64,6 +66,10 @@
     this.abstractValue = abstractValue;
   }
 
+  public void fixupAbstractValue(AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    abstractValue = abstractValue.rewrittenWithLens(appView, lens);
+  }
+
   @Override
   public int getReadBits() {
     return readBits;
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
index 3c689a7..c241c0a 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/OptimizationFeedbackDelayed.java
@@ -177,13 +177,7 @@
   public synchronized void methodReturnsAbstractValue(
       DexEncodedMethod method, AppView<AppInfoWithLiveness> appView, AbstractValue value) {
     if (appView.appInfo().mayPropagateValueFor(method.method)) {
-      UpdatableMethodOptimizationInfo info = getMethodOptimizationInfoForUpdating(method);
-      assert !info.getAbstractReturnValue().isSingleValue()
-              || info.getAbstractReturnValue().asSingleValue() == value
-              || appView.graphLense().lookupPrototypeChanges(method.method).getRewrittenReturnInfo()
-                  != null
-          : "return single value changed from " + info.getAbstractReturnValue() + " to " + value;
-      info.markReturnsAbstractValue(value);
+      getMethodOptimizationInfoForUpdating(method).markReturnsAbstractValue(value);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
index 3b2a85b..366b4d2 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/UpdatableMethodOptimizationInfo.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.graph.AppInfoWithSubtyping;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
@@ -14,6 +15,7 @@
 import com.android.tools.r8.ir.optimize.info.ParameterUsagesInfo.ParameterUsage;
 import com.android.tools.r8.ir.optimize.info.initializer.DefaultInstanceInitializerInfo;
 import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.BooleanUtils;
 import java.util.BitSet;
 import java.util.Set;
@@ -160,6 +162,20 @@
     }
   }
 
+  public UpdatableMethodOptimizationInfo fixupAbstractReturnValue(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    abstractReturnValue = abstractReturnValue.rewrittenWithLens(appView, lens);
+    return this;
+  }
+
+  public UpdatableMethodOptimizationInfo fixupInstanceInitializerInfo(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    if (instanceInitializerInfo != null) {
+      instanceInitializerInfo = instanceInitializerInfo.rewrittenWithLens(appView, lens);
+    }
+    return this;
+  }
+
   private void setFlag(int flag, boolean value) {
     if (value) {
       setFlag(flag);
@@ -384,6 +400,8 @@
   }
 
   void markReturnsAbstractValue(AbstractValue value) {
+    assert !abstractReturnValue.isSingleValue() || abstractReturnValue.asSingleValue() == value
+        : "return single value changed from " + abstractReturnValue + " to " + value;
     abstractReturnValue = value;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/EmptyInstanceFieldInitializationInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/EmptyInstanceFieldInitializationInfoCollection.java
index 6b3cf4c..fd7a84f 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/EmptyInstanceFieldInitializationInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/EmptyInstanceFieldInitializationInfoCollection.java
@@ -4,8 +4,11 @@
 
 package com.android.tools.r8.ir.optimize.info.field;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedField;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.function.BiConsumer;
 
 /**
@@ -40,4 +43,10 @@
   public boolean isEmpty() {
     return true;
   }
+
+  @Override
+  public InstanceFieldInitializationInfoCollection rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldArgumentInitializationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldArgumentInitializationInfo.java
index b9e7652..757eec8 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldArgumentInitializationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldArgumentInitializationInfo.java
@@ -4,6 +4,10 @@
 
 package com.android.tools.r8.ir.optimize.info.field;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
 /**
  * Used to represent that a constructor initializes an instance field on the newly created instance
  * with argument number {@link #argumentIndex} from the constructor's argument list.
@@ -30,4 +34,13 @@
   public InstanceFieldArgumentInitializationInfo asArgumentInitializationInfo() {
     return this;
   }
+
+  @Override
+  public InstanceFieldInitializationInfo rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    // We don't have the context here to determine what should happen. It is the responsibility of
+    // optimizations that change the proto of instance initializers to update the argument
+    // initialization info.
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfo.java
index 2e9285a..37757f1 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfo.java
@@ -4,7 +4,10 @@
 
 package com.android.tools.r8.ir.optimize.info.field;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.value.SingleValue;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 /**
  * Information about the way a constructor initializes an instance field on the newly created
@@ -42,4 +45,7 @@
   default boolean isUnknown() {
     return false;
   }
+
+  InstanceFieldInitializationInfo rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens);
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java
index ed1c4d3..6bf4c74 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldInitializationInfoCollection.java
@@ -4,9 +4,12 @@
 
 package com.android.tools.r8.ir.optimize.info.field;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.function.BiConsumer;
@@ -32,6 +35,9 @@
 
   public abstract boolean isEmpty();
 
+  public abstract InstanceFieldInitializationInfoCollection rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens);
+
   public static class Builder {
 
     Map<DexField, InstanceFieldInitializationInfo> infos = new IdentityHashMap<>();
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java
index e6f84ff..91d1aef 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/InstanceFieldTypeInitializationInfo.java
@@ -4,8 +4,12 @@
 
 package com.android.tools.r8.ir.optimize.info.field;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.EnumValueInfoMapCollection;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.type.ClassTypeLatticeElement;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.Objects;
 
 /**
@@ -43,6 +47,30 @@
   }
 
   @Override
+  public InstanceFieldInitializationInfo rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    EnumValueInfoMapCollection unboxedEnums = appView.unboxedEnums();
+    if (dynamicLowerBoundType != null
+        && unboxedEnums.containsEnum(dynamicLowerBoundType.getClassType())) {
+      // No point in tracking the type of primitives.
+      return UnknownInstanceFieldInitializationInfo.getInstance();
+    }
+    if (dynamicUpperBoundType.isClassType()
+        && unboxedEnums.containsEnum(
+            dynamicUpperBoundType.asClassTypeLatticeElement().getClassType())) {
+      // No point in tracking the type of primitives.
+      return UnknownInstanceFieldInitializationInfo.getInstance();
+    }
+    return new InstanceFieldTypeInitializationInfo(
+        dynamicLowerBoundType != null
+            ? dynamicLowerBoundType
+                .fixupClassTypeReferences(lens::lookupType, appView.withSubtyping())
+                .asClassTypeLatticeElement()
+            : null,
+        dynamicUpperBoundType.fixupClassTypeReferences(lens::lookupType, appView.withSubtyping()));
+  }
+
+  @Override
   public int hashCode() {
     return Objects.hash(dynamicLowerBoundType, dynamicUpperBoundType);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java
index 5883be6..7c7a563 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/NonTrivialInstanceFieldInitializationInfoCollection.java
@@ -4,9 +4,13 @@
 
 package com.android.tools.r8.ir.optimize.info.field;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexDefinitionSupplier;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexField;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.function.BiConsumer;
 
@@ -47,4 +51,17 @@
   public boolean isEmpty() {
     return false;
   }
+
+  @Override
+  public InstanceFieldInitializationInfoCollection rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    Map<DexField, InstanceFieldInitializationInfo> rewrittenInfos = new IdentityHashMap<>();
+    infos.forEach(
+        (field, info) -> {
+          DexField rewrittenField = lens.lookupField(field);
+          InstanceFieldInitializationInfo rewrittenInfo = info.rewrittenWithLens(appView, lens);
+          rewrittenInfos.put(rewrittenField, rewrittenInfo);
+        });
+    return new NonTrivialInstanceFieldInitializationInfoCollection(rewrittenInfos);
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/field/UnknownInstanceFieldInitializationInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/field/UnknownInstanceFieldInitializationInfo.java
index a10f045..b2b6ce9 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/field/UnknownInstanceFieldInitializationInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/field/UnknownInstanceFieldInitializationInfo.java
@@ -4,6 +4,10 @@
 
 package com.android.tools.r8.ir.optimize.info.field;
 
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.GraphLense;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
+
 /**
  * Represents that no information is known about the way a particular constructor initializes an
  * instance field of the newly created instance.
@@ -23,4 +27,10 @@
   public boolean isUnknown() {
     return true;
   }
+
+  @Override
+  public InstanceFieldInitializationInfo rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java
index 20aff53..4065fb0 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/DefaultInstanceInitializerInfo.java
@@ -4,11 +4,14 @@
 
 package com.android.tools.r8.ir.optimize.info.initializer;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.AbstractFieldSet;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.UnknownFieldSet;
 import com.android.tools.r8.ir.optimize.info.field.EmptyInstanceFieldInitializationInfoCollection;
 import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class DefaultInstanceInitializerInfo extends InstanceInitializerInfo {
 
@@ -22,11 +25,6 @@
   }
 
   @Override
-  public boolean isDefaultInfo() {
-    return true;
-  }
-
-  @Override
   public DexMethod getParent() {
     return null;
   }
@@ -55,4 +53,10 @@
   public boolean receiverNeverEscapesOutsideConstructorChain() {
     return false;
   }
+
+  @Override
+  public InstanceInitializerInfo rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return this;
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java
index b27888e..1745e7d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/InstanceInitializerInfo.java
@@ -4,9 +4,12 @@
 
 package com.android.tools.r8.ir.optimize.info.initializer;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.AbstractFieldSet;
 import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public abstract class InstanceInitializerInfo {
 
@@ -53,7 +56,6 @@
     return !receiverNeverEscapesOutsideConstructorChain();
   }
 
-  public boolean isDefaultInfo() {
-    return false;
-  }
+  public abstract InstanceInitializerInfo rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens);
 }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java
index 4e19cef..f549927 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/info/initializer/NonTrivialInstanceInitializerInfo.java
@@ -4,13 +4,16 @@
 
 package com.android.tools.r8.ir.optimize.info.initializer;
 
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedField;
 import com.android.tools.r8.graph.DexMethod;
+import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.AbstractFieldSet;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.ConcreteMutableFieldSet;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.EmptyFieldSet;
 import com.android.tools.r8.ir.analysis.fieldvalueanalysis.UnknownFieldSet;
 import com.android.tools.r8.ir.optimize.info.field.InstanceFieldInitializationInfoCollection;
+import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public final class NonTrivialInstanceInitializerInfo extends InstanceInitializerInfo {
 
@@ -79,6 +82,16 @@
     return (data & RECEIVER_NEVER_ESCAPE_OUTSIDE_CONSTRUCTOR_CHAIN) != 0;
   }
 
+  @Override
+  public NonTrivialInstanceInitializerInfo rewrittenWithLens(
+      AppView<AppInfoWithLiveness> appView, GraphLense lens) {
+    return new NonTrivialInstanceInitializerInfo(
+        data,
+        fieldInitializationInfos.rewrittenWithLens(appView, lens),
+        readSet.rewrittenWithLens(appView, lens),
+        lens.getRenamedMethodSignature(parent));
+  }
+
   public static class Builder {
 
     private final InstanceFieldInitializationInfoCollection instanceFieldInitializationInfos;