Account for AppInfoWithClassHierarchy in IR processing in R8

Bug: b/205810841
Change-Id: If31e8329f5b944803fa4a6195d28b9efda2efb15
diff --git a/src/main/java/com/android/tools/r8/graph/AppView.java b/src/main/java/com/android/tools/r8/graph/AppView.java
index db99838..300092c 100644
--- a/src/main/java/com/android/tools/r8/graph/AppView.java
+++ b/src/main/java/com/android/tools/r8/graph/AppView.java
@@ -697,9 +697,13 @@
     // Even if we can compute isSubtype by having class hierarchy we may not be allowed to ask the
     // question for all code paths in D8. Having the check for liveness ensure that we are in R8
     // territory.
-    return appInfo().hasLiveness()
-        ? OptionalBool.of(appInfo().withLiveness().isSubtype(subtype, supertype))
-        : OptionalBool.unknown();
+    if (hasClassHierarchy()) {
+      return OptionalBool.of(appInfo().withClassHierarchy().isSubtype(subtype, supertype));
+    }
+    if (subtype == supertype || supertype == dexItemFactory().objectType) {
+      return OptionalBool.TRUE;
+    }
+    return OptionalBool.unknown();
   }
 
   public boolean isCfByteCodePassThrough(DexEncodedMethod method) {
diff --git a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
index 658c2c0..f61a52b 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProgramClass.java
@@ -19,8 +19,8 @@
 import com.android.tools.r8.kotlin.KotlinClassLevelInfo;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.origin.Origin;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.synthesis.SyntheticMarker;
+import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.TraversalContinuation;
 import com.android.tools.r8.utils.structural.Ordered;
 import com.android.tools.r8.utils.structural.StructuralItem;
@@ -445,13 +445,11 @@
     if (isFinal()) {
       return true;
     }
-    if (appView.enableWholeProgramOptimizations()) {
-      assert appView.appInfo().hasLiveness();
-      AppInfoWithLiveness appInfo = appView.appInfo().withLiveness();
-      if (appInfo.isPinned(type)) {
-        return false;
-      }
-      return !appInfo.isInstantiatedIndirectly(this);
+    if (appView.hasLiveness()) {
+      assert appView.enableWholeProgramOptimizations();
+      InternalOptions options = appView.options();
+      return !appView.getKeepInfo(this).isPinned(options)
+          && !appView.appInfoWithLiveness().isInstantiatedIndirectly(this);
     }
     return false;
   }
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 716396d..7152fa6 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
@@ -9,6 +9,7 @@
 import com.android.tools.r8.cf.code.CfConstClass;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AccessControl;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
@@ -21,7 +22,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class ConstClass extends ConstInstruction {
 
@@ -133,8 +133,9 @@
       return true;
     }
 
-    assert appView.appInfo().hasLiveness();
-    AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+    assert appView.appInfo().hasClassHierarchy();
+    AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+        appView.withClassHierarchy();
 
     DexClass clazz = appView.definitionFor(baseType);
     // * Check that the class and its super types are present.
@@ -142,7 +143,8 @@
       return true;
     }
     // * Check that the class is accessible.
-    if (AccessControl.isClassAccessible(clazz, context, appViewWithLiveness).isPossiblyFalse()) {
+    if (AccessControl.isClassAccessible(clazz, context, appViewWithClassHierarchy)
+        .isPossiblyFalse()) {
       return true;
     }
     return false;
@@ -202,7 +204,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     if (!instructionMayHaveSideEffects(appView, context)) {
       return appView.abstractValueFactory().createSingleConstClassValue(clazz);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
index 4111b17..958816b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -16,6 +16,7 @@
 import com.android.tools.r8.code.ConstWide32;
 import com.android.tools.r8.code.ConstWideHigh16;
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
@@ -27,7 +28,6 @@
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.InternalOutputMode;
 import com.android.tools.r8.utils.NumberUtils;
 import java.util.Set;
@@ -340,7 +340,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     return appView.abstractValueFactory().createSingleNumberValue(value);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index a3efba8..3df5d13 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.cf.TypeVerificationHelper;
 import com.android.tools.r8.cf.code.CfConstString;
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
@@ -20,7 +21,6 @@
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.DeadCodeRemover.DeadInstructionResult;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.io.UTFDataFormatException;
 
 public class ConstString extends ConstInstruction {
@@ -164,7 +164,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     if (!instructionInstanceCanThrow()) {
       return appView.abstractValueFactory().createSingleStringValue(value);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
index 4dc3985..b7820c1 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.cf.TypeVerificationHelper;
 import com.android.tools.r8.cf.code.CfDexItemBasedConstString;
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexType;
@@ -20,7 +21,6 @@
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class DexItemBasedConstString extends ConstInstruction {
 
@@ -165,7 +165,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     return appView
         .abstractValueFactory()
         .createSingleDexItemBasedStringValue(item, nameComputationInfo);
diff --git a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
index c65bccc..29b4de7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/FieldInstruction.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.code;
 
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexEncodedField;
@@ -209,7 +210,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     assert isFieldGet();
     DexEncodedField field = appView.appInfo().resolveField(getField()).getResolvedField();
     if (field != null) {
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 564eaf1..feaca12 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
@@ -7,6 +7,7 @@
 import com.android.tools.r8.cf.TypeVerificationHelper;
 import com.android.tools.r8.errors.Unimplemented;
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -180,7 +181,7 @@
   }
 
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     assert hasOutValue();
     return UnknownValue.getInstance();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
index 2fc4aff..1d259f6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethod.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.cf.TypeVerificationHelper;
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClassAndMethod;
 import com.android.tools.r8.graph.DexEncodedMethod;
@@ -247,7 +248,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     assert hasOutValue();
     DexClassAndMethod method = lookupSingleTarget(appView, context);
     if (method != null) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
index d01bcaa..cdf992b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMethodWithReceiver.java
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.ir.code;
 
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexClassAndMethod;
@@ -192,11 +193,12 @@
       return true;
     }
 
-    assert appView.appInfo().hasLiveness();
-    AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+    assert appView.appInfo().hasClassHierarchy();
+    AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+        appView.withClassHierarchy();
 
     SingleResolutionResult resolutionResult =
-        appViewWithLiveness
+        appViewWithClassHierarchy
             .appInfo()
             .resolveMethod(getInvokedMethod(), getInterfaceBit())
             .asSingleResolution();
@@ -205,9 +207,7 @@
     }
 
     // Verify that the target method is accessible in the current context.
-    if (resolutionResult
-        .isAccessibleFrom(context, appViewWithLiveness.appInfo())
-        .isPossiblyFalse()) {
+    if (resolutionResult.isAccessibleFrom(context, appViewWithClassHierarchy).isPossiblyFalse()) {
       return true;
     }
 
@@ -215,14 +215,16 @@
       return false;
     }
 
-    DexEncodedMethod resolvedMethod = resolutionResult.getResolvedMethod();
-    if (appViewWithLiveness.appInfo().noSideEffects.containsKey(getInvokedMethod())
-        || appViewWithLiveness.appInfo().noSideEffects.containsKey(resolvedMethod.getReference())) {
-      return false;
+    DexClassAndMethod resolvedMethod = resolutionResult.getResolutionPair();
+    if (appView.hasLiveness()) {
+      if (appView.appInfoWithLiveness().isAssumeNoSideEffectsMethod(getInvokedMethod())
+          || appView.appInfoWithLiveness().isAssumeNoSideEffectsMethod(resolvedMethod)) {
+        return false;
+      }
     }
 
     // Find the target and check if the invoke may have side effects.
-    DexClassAndMethod singleTarget = lookupSingleTarget(appViewWithLiveness, context);
+    DexClassAndMethod singleTarget = lookupSingleTarget(appView, context);
     if (singleTarget == null) {
       return true;
     }
@@ -235,8 +237,10 @@
     }
 
     // Verify that the target method does not have side-effects.
-    if (appViewWithLiveness.appInfo().noSideEffects.containsKey(singleTarget.getReference())) {
-      return false;
+    if (appView.hasLiveness()) {
+      if (appView.appInfoWithLiveness().isAssumeNoSideEffectsMethod(singleTarget)) {
+        return false;
+      }
     }
 
     DexEncodedMethod singleTargetDefinition = singleTarget.getDefinition();
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
index 63df06a..e750ab3 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeMultiNewArray.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.cf.code.CfMultiANewArray;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AccessControl;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
@@ -18,7 +19,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.utils.LongInterval;
 import java.util.List;
 
@@ -134,8 +134,9 @@
       return true;
     }
 
-    assert appView.appInfo().hasLiveness();
-    AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+    assert appView.appInfo().hasClassHierarchy();
+    AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+        appView.withClassHierarchy();
 
     // Check if the type is guaranteed to be present.
     DexClass clazz = appView.definitionFor(baseType);
@@ -149,7 +150,8 @@
     }
 
     // Check if the type is guaranteed to be accessible.
-    if (AccessControl.isClassAccessible(clazz, context, appViewWithLiveness).isPossiblyFalse()) {
+    if (AccessControl.isClassAccessible(clazz, context, appViewWithClassHierarchy)
+        .isPossiblyFalse()) {
       return true;
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
index 636468c..1b356e3 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeNewArray.java
@@ -9,6 +9,7 @@
 import com.android.tools.r8.code.FilledNewArrayRange;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AccessControl;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
@@ -22,7 +23,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.List;
 
 public class InvokeNewArray extends Invoke {
@@ -144,7 +144,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     if (!instructionMayHaveSideEffects(appView, context)) {
       int size = inValues.size();
       return StatefulObjectValue.create(
@@ -175,8 +175,9 @@
       return true;
     }
 
-    assert appView.appInfo().hasLiveness();
-    AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+    assert appView.appInfo().hasClassHierarchy();
+    AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+        appView.withClassHierarchy();
 
     // Check if the type is guaranteed to be present.
     DexClass clazz = appView.definitionFor(baseType);
@@ -191,7 +192,8 @@
     }
 
     // Check if the type is guaranteed to be accessible.
-    if (AccessControl.isClassAccessible(clazz, context, appViewWithLiveness).isPossiblyFalse()) {
+    if (AccessControl.isClassAccessible(clazz, context, appViewWithClassHierarchy)
+        .isPossiblyFalse()) {
       return true;
     }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
index 3d6fb7d..500766c 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayEmpty.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.cf.code.CfNewArray;
 import com.android.tools.r8.code.NewArray;
 import com.android.tools.r8.dex.Constants;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
@@ -21,7 +22,6 @@
 import com.android.tools.r8.ir.optimize.DeadCodeRemover.DeadInstructionResult;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class NewArrayEmpty extends Instruction {
 
@@ -88,7 +88,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     if (!instructionMayHaveSideEffects(appView, context) && size().getType().isInt()) {
       assert !instructionInstanceCanThrow();
       return StatefulObjectValue.create(
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
index fb04f03..260689f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewArrayFilledData.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.code.FillArrayDataPayload;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.ProgramMethod;
 import com.android.tools.r8.ir.analysis.value.AbstractValue;
@@ -17,7 +18,6 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
-import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.Arrays;
 
 public class NewArrayFilledData extends Instruction {
@@ -125,7 +125,7 @@
 
   @Override
   public AbstractValue getAbstractValue(
-      AppView<AppInfoWithLiveness> appView, ProgramMethod context) {
+      AppView<? extends AppInfoWithClassHierarchy> appView, ProgramMethod context) {
     if (!instructionMayHaveSideEffects(appView, context) && size <= Integer.MAX_VALUE) {
       assert !instructionInstanceCanThrow();
       return StatefulObjectValue.create(
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
index 3aff847..e99029a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewInstance.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.cf.code.CfNew;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AccessControl;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexItemFactory;
@@ -158,8 +159,9 @@
           && dexItemFactory.libraryClassesWithoutStaticInitialization.contains(clazz));
     }
 
-    assert appView.appInfo().hasLiveness();
-    AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+    assert appView.appInfo().hasClassHierarchy();
+    AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+        appView.withClassHierarchy();
 
     if (clazz.isPrimitiveType() || clazz.isArrayType()) {
       assert false : "Unexpected new-instance instruction with primitive or array type";
@@ -177,19 +179,20 @@
     }
 
     // Verify that the instruction does not lead to an IllegalAccessError.
-    if (AccessControl.isClassAccessible(definition, context, appViewWithLiveness)
+    if (AccessControl.isClassAccessible(definition, context, appViewWithClassHierarchy)
         .isPossiblyFalse()) {
       return true;
     }
 
     // Verify that the new-instance instruction won't lead to class initialization.
-    if (definition.classInitializationMayHaveSideEffectsInContext(appViewWithLiveness, context)) {
+    if (definition.classInitializationMayHaveSideEffectsInContext(
+        appViewWithClassHierarchy, context)) {
       return true;
     }
 
     // Verify that the object does not have a finalizer.
     MethodResolutionResult finalizeResolutionResult =
-        appViewWithLiveness
+        appViewWithClassHierarchy
             .appInfo()
             .resolveMethodOnClass(dexItemFactory.objectMembers.finalize, clazz);
     if (finalizeResolutionResult.isSingleResolution()) {
diff --git a/src/main/java/com/android/tools/r8/ir/code/Value.java b/src/main/java/com/android/tools/r8/ir/code/Value.java
index cc59793..bb83120 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Value.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Value.java
@@ -846,7 +846,7 @@
       return UnknownValue.getInstance();
     }
 
-    return root.definition.getAbstractValue(appView.withLiveness(), context);
+    return root.definition.getAbstractValue(appView.withClassHierarchy(), context);
   }
 
   public boolean isDefinedByInstructionSatisfying(Predicate<Instruction> predicate) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index a0aec41..2289a72 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -14,6 +14,7 @@
 import com.android.tools.r8.errors.CompilationError;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AccessControl;
+import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexClass;
@@ -3011,11 +3012,12 @@
   // it with a block throwing a null value (which should result in NPE). Note that this throw is not
   // expected to be ever reached, but is intended to satisfy verifier.
   public void optimizeAlwaysThrowingInstructions(IRCode code) {
-    if (!appView.appInfo().hasLiveness()) {
+    if (!appView.appInfo().hasClassHierarchy()) {
       return;
     }
 
-    AppView<AppInfoWithLiveness> appViewWithLiveness = appView.withLiveness();
+    AppView<? extends AppInfoWithClassHierarchy> appViewWithClassHierarchy =
+        appView.withClassHierarchy();
     Set<Value> affectedValues = Sets.newIdentityHashSet();
     Set<BasicBlock> blocksToRemove = Sets.newIdentityHashSet();
     ListIterator<BasicBlock> blockIterator = code.listIterator();
@@ -3065,7 +3067,7 @@
               }
             }
             instructionIterator.replaceCurrentInstructionWithThrowNull(
-                appViewWithLiveness, code, blockIterator, blocksToRemove, affectedValues);
+                appViewWithClassHierarchy, code, blockIterator, blocksToRemove, affectedValues);
             continue;
           }
         }
@@ -3075,8 +3077,7 @@
         }
 
         InvokeMethod invoke = instruction.asInvokeMethod();
-        DexClassAndMethod singleTarget =
-            invoke.lookupSingleTarget(appView.withLiveness(), code.context());
+        DexClassAndMethod singleTarget = invoke.lookupSingleTarget(appView, code.context());
         if (singleTarget == null) {
           continue;
         }
@@ -3102,7 +3103,7 @@
           instructionIterator.setInsertionPosition(invoke.getPosition());
           instructionIterator.next();
           instructionIterator.replaceCurrentInstructionWithThrowNull(
-              appViewWithLiveness, code, blockIterator, blocksToRemove, affectedValues);
+              appViewWithClassHierarchy, code, blockIterator, blocksToRemove, affectedValues);
           instructionIterator.unsetInsertionPosition();
         }
       }