Merge "Extend Instruction#canBeDaedCode to receive AppView."
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
index 21bc624..1d42746 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingDefinition.java
@@ -9,8 +9,10 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class AlwaysMaterializingDefinition extends ConstInstruction {
 
@@ -19,7 +21,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // This instruction may never be considered dead as it must remain.
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
index 197afaa..37bbd07 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
@@ -7,11 +7,13 @@
 import com.android.tools.r8.cf.code.CfNop;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 
 public class AlwaysMaterializingNop extends Instruction {
 
@@ -20,7 +22,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     return false;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
index b5cd950..ecb7a81 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingUser.java
@@ -6,11 +6,13 @@
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 
 public class AlwaysMaterializingUser extends Instruction {
 
@@ -19,7 +21,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // This instruction may never be considered dead as it must remain.
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Argument.java b/src/main/java/com/android/tools/r8/ir/code/Argument.java
index 1bed0cc..4ae0c3e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Argument.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Argument.java
@@ -8,12 +8,14 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 
 /**
  * Argument pseudo instruction used to introduce values for all arguments for SSA conversion.
@@ -26,7 +28,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appview, AppInfo appInfo, IRCode code) {
     // Never remove argument instructions. That would change the signature of the method.
     // TODO(b/65810338): If we can tell that a method never uses an argument we might be able to
     // rewrite the signature and call-sites.
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
index 7263948..34a0041 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayPut.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
@@ -23,6 +24,7 @@
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.util.Arrays;
 
 public class ArrayPut extends Instruction implements ImpreciseMemberTypeInstruction {
@@ -128,7 +130,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // ArrayPut has side-effects on input values.
     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 7610f9c..b7a1f70 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.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.Nullability;
@@ -17,6 +18,7 @@
 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.Enqueuer.AppInfoWithLiveness;
 
 public class ConstClass extends ConstInstruction {
 
@@ -87,7 +89,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // A const-class instruction can be dead code only if the resulting program is known to contain
     // the class mentioned.
     DexType baseType = clazz.toBaseType(appInfo.dexItemFactory);
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 692dba2..48cc0ba 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
@@ -8,6 +8,7 @@
 import com.android.tools.r8.cf.code.CfConstString;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.Nullability;
@@ -15,6 +16,7 @@
 import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.io.UTFDataFormatException;
 
 public class ConstString extends ConstInstruction {
@@ -115,7 +117,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // No side-effect, such as throwing an exception, in CF.
     return code.options.isGeneratingClassFiles() || !instructionInstanceCanThrow();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
index 8a778b9..1c372ed 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalRead.java
@@ -6,11 +6,13 @@
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 
 public class DebugLocalRead extends Instruction {
   private static final String ERROR_MESSAGE = "Unexpected attempt to emit debug-local read.";
@@ -61,7 +63,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // Reads are never dead code.
     // They should also have a non-empty set of debug values (see RegAlloc::computeDebugInfo)
     return false;
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
index 9b8a00e..a2aa761 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalsChange.java
@@ -6,12 +6,14 @@
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+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.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.StringUtils;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
@@ -73,7 +75,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     return false;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
index ea4aebc..6990e18 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugPosition.java
@@ -7,11 +7,13 @@
 import com.android.tools.r8.cf.code.CfNop;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 
 public class DebugPosition extends Instruction {
 
@@ -57,7 +59,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     return false;
   }
 
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 c3b8f80..0f00350 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
@@ -8,6 +8,7 @@
 import com.android.tools.r8.cf.code.CfDexItemBasedConstString;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.Nullability;
@@ -16,6 +17,7 @@
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.ReflectionOptimizer.ClassNameComputationInfo;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 
 public class DexItemBasedConstString extends ConstInstruction {
 
@@ -110,7 +112,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // No side-effect, such as throwing an exception, in CF.
     return true;
   }
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 d8500e6..afe55d1 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
@@ -25,6 +25,7 @@
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.CfgPrinter;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.StringUtils.BraceType;
@@ -510,7 +511,8 @@
   }
 
   /** Returns true is this instruction can be treated as dead code if its outputs are not used. */
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     return !instructionInstanceCanThrow();
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
index 7fa8c80..8e7c646 100644
--- a/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/JumpInstruction.java
@@ -4,9 +4,11 @@
 package com.android.tools.r8.ir.code;
 
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.util.List;
 
 public abstract class JumpInstruction extends Instruction {
@@ -32,7 +34,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     return false;
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/MoveException.java b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
index 325016e..e89778e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/MoveException.java
+++ b/src/main/java/com/android/tools/r8/ir/code/MoveException.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.cf.TypeVerificationHelper;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
@@ -14,6 +15,7 @@
 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.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.InternalOptions;
 
 public class MoveException extends Instruction {
@@ -70,7 +72,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     return !(code.options.debug || code.method.getOptimizationInfo().isReachabilitySensitive())
         && code.options.isGeneratingDex();
   }
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 e235682..5ce2193 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
@@ -9,6 +9,7 @@
 import com.android.tools.r8.code.NewArray;
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
@@ -16,6 +17,7 @@
 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.Enqueuer.AppInfoWithLiveness;
 
 public class NewArrayEmpty extends Instruction {
 
@@ -72,7 +74,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     if (instructionInstanceCanThrow()) {
       return false;
     }
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 f534fb9..f107c90 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
@@ -9,11 +9,13 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 import java.util.Arrays;
 
 public class NewArrayFilledData extends Instruction {
@@ -74,7 +76,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     if (!src().getTypeLattice().isNullable() && src().numberOfAllUsers() == 1) {
       // The NewArrayFilledData instruction is only inserted by an R8 optimization following
       // a NewArrayEmpty when there are more than one entry.
diff --git a/src/main/java/com/android/tools/r8/ir/code/Pop.java b/src/main/java/com/android/tools/r8/ir/code/Pop.java
index 273e57e..41d17b0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Pop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Pop.java
@@ -7,11 +7,13 @@
 import com.android.tools.r8.cf.code.CfStackInstruction;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 
 public class Pop extends Instruction {
 
@@ -81,7 +83,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     // Pop cannot be dead code as it modifies the stack height.
     return false;
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Store.java b/src/main/java/com/android/tools/r8/ir/code/Store.java
index 202bac6..07cb184 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Store.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Store.java
@@ -10,12 +10,14 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 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.Enqueuer.AppInfoWithLiveness;
 
 public class Store extends Instruction {
 
@@ -89,7 +91,8 @@
   }
 
   @Override
-  public boolean canBeDeadCode(AppInfo appInfo, IRCode code) {
+  public boolean canBeDeadCode(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, IRCode code) {
     return !(outValue instanceof FixedLocalValue);
   }
 
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 374acd5..55bc508 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
@@ -6,12 +6,14 @@
 import com.android.tools.r8.dex.Constants;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
 import com.android.tools.r8.ir.regalloc.LiveIntervals;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.position.MethodPosition;
+import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.android.tools.r8.utils.LongInterval;
 import com.android.tools.r8.utils.Reporter;
 import com.android.tools.r8.utils.StringDiagnostic;
@@ -859,12 +861,13 @@
     }
   }
 
-  public boolean isDead(AppInfo appInfo) {
+  public boolean isDead(AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo) {
     // Totally unused values are trivially dead.
-    return !isUsed() || isDead(appInfo, new HashSet<>());
+    return !isUsed() || isDead(appView, appInfo, new HashSet<>());
   }
 
-  protected boolean isDead(AppInfo appInfo, Set<Value> active) {
+  protected boolean isDead(
+      AppView<? extends AppInfoWithLiveness> appView, AppInfo appInfo, Set<Value> active) {
     // If the value has debug users we cannot eliminate it since it represents a value in a local
     // variable that should be visible in the debugger.
     if (numberOfDebugUsers() != 0) {
@@ -874,19 +877,19 @@
     // currently active values.
     active.add(this);
     for (Instruction instruction : uniqueUsers()) {
-      if (!instruction.canBeDeadCode(appInfo, null)) {
+      if (!instruction.canBeDeadCode(appView, appInfo, null)) {
         return false;
       }
       Value outValue = instruction.outValue();
       // Instructions with no out value cannot be dead code by the current definition
       // (unused out value). They typically side-effect input values or deals with control-flow.
       assert outValue != null;
-      if (!active.contains(outValue) && !outValue.isDead(appInfo, active)) {
+      if (!active.contains(outValue) && !outValue.isDead(appView, appInfo, active)) {
         return false;
       }
     }
     for (Phi phi : uniquePhiUsers()) {
-      if (!active.contains(phi) && !phi.isDead(appInfo, active)) {
+      if (!active.contains(phi) && !phi.isDead(appView, appInfo, active)) {
         return false;
       }
     }
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 8571409..cb7a5d5 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
@@ -196,7 +196,8 @@
             ? new CovariantReturnTypeAnnotationTransformer(this, appInfo.dexItemFactory)
             : null;
     this.stringOptimizer = new StringOptimizer(appInfo, options.getInternalOutputMode());
-    this.enableWholeProgramOptimizations = appView != null;
+    this.enableWholeProgramOptimizations =
+        appView != null && appView.enableWholeProgramOptimizations();
     if (enableWholeProgramOptimizations) {
       assert appInfo.hasLiveness();
       AppInfoWithLiveness appInfoWithLiveness = appInfo.withLiveness();
@@ -241,8 +242,7 @@
     this.classStaticizer = options.enableClassStaticizer && appInfo.hasLiveness()
         ? new ClassStaticizer(appInfo.withLiveness(), this) : null;
     this.deadCodeRemover =
-        new DeadCodeRemover(
-            appInfo, codeRewriter, graphLense(), options, enableWholeProgramOptimizations);
+        new DeadCodeRemover(appView, appInfo, codeRewriter, graphLense(), options);
     this.idempotentFunctionCallCanonicalizer =
         new IdempotentFunctionCallCanonicalizer(appInfo.dexItemFactory);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
index fa259c2..aadb088 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/DeadCodeRemover.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.ir.optimize;
 
 import com.android.tools.r8.graph.AppInfo;
+import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexClass;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
@@ -26,6 +27,7 @@
 
 public class DeadCodeRemover {
 
+  private final AppView<? extends AppInfoWithLiveness> appView;
   private final AppInfo appInfo;
   private final CodeRewriter codeRewriter;
   private final GraphLense graphLense;
@@ -33,16 +35,18 @@
   private final boolean enableWholeProgramOptimizations;
 
   public DeadCodeRemover(
+      AppView<? extends AppInfoWithLiveness> appView,
       AppInfo appInfo,
       CodeRewriter codeRewriter,
       GraphLense graphLense,
-      InternalOptions options,
-      boolean enableWholeProgramOptimizations) {
+      InternalOptions options) {
+    this.appView = appView;
     this.appInfo = appInfo;
     this.codeRewriter = codeRewriter;
     this.graphLense = graphLense;
     this.options = options;
-    this.enableWholeProgramOptimizations = enableWholeProgramOptimizations;
+    this.enableWholeProgramOptimizations =
+        appView != null && appView.enableWholeProgramOptimizations();
   }
 
   public void run(IRCode code) {
@@ -54,8 +58,8 @@
     do {
       worklist.addAll(code.blocks);
       for (BasicBlock block = worklist.poll(); block != null; block = worklist.poll()) {
-        removeDeadInstructions(worklist, code, block, appInfo);
-        removeDeadPhis(worklist, block, appInfo);
+        removeDeadInstructions(worklist, code, block, appView, appInfo);
+        removeDeadPhis(worklist, block, appView, appInfo);
       }
     } while (removeUnneededCatchHandlers(code));
     assert code.isConsistentSSA();
@@ -86,11 +90,14 @@
   }
 
   private static void removeDeadPhis(
-      Queue<BasicBlock> worklist, BasicBlock block, AppInfo appInfo) {
+      Queue<BasicBlock> worklist,
+      BasicBlock block,
+      AppView<? extends AppInfoWithLiveness> appView,
+      AppInfo appInfo) {
     Iterator<Phi> phiIt = block.getPhis().iterator();
     while (phiIt.hasNext()) {
       Phi phi = phiIt.next();
-      if (phi.isDead(appInfo)) {
+      if (phi.isDead(appView, appInfo)) {
         phiIt.remove();
         for (Value operand : phi.getOperands()) {
           operand.removePhiUser(phi);
@@ -101,7 +108,11 @@
   }
 
   private static void removeDeadInstructions(
-      Queue<BasicBlock> worklist, IRCode code, BasicBlock block, AppInfo appInfo) {
+      Queue<BasicBlock> worklist,
+      IRCode code,
+      BasicBlock block,
+      AppView<? extends AppInfoWithLiveness> appView,
+      AppInfo appInfo) {
     InstructionListIterator iterator = block.listIterator(block.getInstructions().size());
     while (iterator.hasPrevious()) {
       Instruction current = iterator.previous();
@@ -111,11 +122,11 @@
           && !current.outValue().isUsed()) {
         current.setOutValue(null);
       }
-      if (!current.canBeDeadCode(appInfo, code)) {
+      if (!current.canBeDeadCode(appView, appInfo, code)) {
         continue;
       }
       Value outValue = current.outValue();
-      if (outValue != null && !outValue.isDead(appInfo)) {
+      if (outValue != null && !outValue.isDead(appView, appInfo)) {
         continue;
       }
       updateWorklist(worklist, current);