Merge "Refine inlining constraints with target holder."
diff --git a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
index 9a44dde..a6032e4 100644
--- a/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
+++ b/src/main/java/com/android/tools/r8/graph/DexEncodedMethod.java
@@ -32,7 +32,7 @@
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.Inliner.Reason;
 import com.android.tools.r8.ir.regalloc.RegisterAllocator;
 import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
@@ -57,6 +57,7 @@
    * <p>
    * We also use this enum to encode under what constraints a method may be inlined.
    */
+  // TODO(b/111080693): Need to extend this to a state with the context.
   public enum CompilationState {
     /**
      * Has not been processed, yet.
@@ -72,7 +73,7 @@
      */
     PROCESSED_INLINING_CANDIDATE_ANY,
     /**
-     * Code also contains instructions that access protected entities that reside in a differnt
+     * Code also contains instructions that access protected entities that reside in a different
      * package and hence require subclass relationship to be visible.
      */
     PROCESSED_INLINING_CANDIDATE_SUBCLASS,
@@ -96,6 +97,8 @@
   public DexAnnotationSet annotations;
   public ParameterAnnotationsList parameterAnnotationsList;
   private Code code;
+  // TODO(b/111080693): towards finer-grained inlining constraints,
+  //   we need to maintain a set of states with (potentially different) contexts.
   private CompilationState compilationState = CompilationState.NOT_PROCESSED;
   private OptimizationInfo optimizationInfo = DefaultOptimizationInfo.DEFAULT;
   private int classFileVersion = -1;
@@ -208,6 +211,7 @@
       assert isInliningCandidate(containerType, Reason.SIMPLE, appInfo);
       return true;
     }
+    // TODO(b/111080693): inlining candidate should satisfy all states if multiple states are there.
     switch (compilationState) {
       case PROCESSED_INLINING_CANDIDATE_ANY:
         return true;
@@ -222,9 +226,9 @@
     }
   }
 
-  public boolean markProcessed(Constraint state) {
+  public boolean markProcessed(ConstraintWithTarget state) {
     CompilationState prevCompilationState = compilationState;
-    switch (state) {
+    switch (state.constraint) {
       case ALWAYS:
         compilationState = PROCESSED_INLINING_CANDIDATE_ANY;
         break;
diff --git a/src/main/java/com/android/tools/r8/graph/JarCode.java b/src/main/java/com/android/tools/r8/graph/JarCode.java
index 2c37c6a..a48841f 100644
--- a/src/main/java/com/android/tools/r8/graph/JarCode.java
+++ b/src/main/java/com/android/tools/r8/graph/JarCode.java
@@ -10,7 +10,7 @@
 import com.android.tools.r8.ir.code.ValueNumberGenerator;
 import com.android.tools.r8.ir.conversion.IRBuilder;
 import com.android.tools.r8.ir.conversion.JarSourceCode;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.jar.InliningConstraintVisitor;
 import com.android.tools.r8.jar.JarRegisterEffectsVisitor;
 import com.android.tools.r8.naming.ClassNameMapper;
@@ -173,7 +173,7 @@
             DescriptorUtils.getDescriptorFromClassBinaryName(tryCatchBlockNode.type))));
   }
 
-  public Constraint computeInliningConstraint(
+  public ConstraintWithTarget computeInliningConstraint(
       DexEncodedMethod encodedMethod,
       AppInfoWithLiveness appInfo,
       GraphLense graphLense,
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 6948a08..20d7bf4 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
@@ -8,7 +8,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 
@@ -58,7 +58,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forAlwaysMaterializingUser();
   }
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 cff655a..c8240a0 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
@@ -10,7 +10,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 
@@ -76,7 +76,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forArgument();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
index 01101f3..758252b 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayGet.java
@@ -21,7 +21,7 @@
 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.Constraint;
+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 java.util.Arrays;
@@ -133,7 +133,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forArrayGet();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java b/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
index cc358f0..445c9ed 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArrayLength.java
@@ -13,7 +13,7 @@
 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.Constraint;
+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 java.util.function.Function;
@@ -90,7 +90,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forArrayLength();
   }
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 023afce..0282ffa 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
@@ -17,7 +17,7 @@
 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.Constraint;
+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.utils.InternalOptions;
@@ -154,7 +154,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forArrayPut();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Binop.java b/src/main/java/com/android/tools/r8/ir/code/Binop.java
index e5190bb..30fdc59 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Binop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Binop.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+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 java.util.function.Function;
@@ -124,7 +124,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forBinop();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
index dba575f..cee01eb 100644
--- a/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
+++ b/src/main/java/com/android/tools/r8/ir/code/CheckCast.java
@@ -15,7 +15,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 
@@ -113,7 +113,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forCheckCast(type, invocationContext);
   }
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 3041aaf..c5a0a11 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
@@ -13,7 +13,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 import java.util.function.Function;
@@ -99,7 +99,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forConstClass(clazz, invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java b/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java
index f6e212d..a6ac01d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstInstruction.java
@@ -4,7 +4,7 @@
 package com.android.tools.r8.ir.code;
 
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 
 public abstract class ConstInstruction extends Instruction {
@@ -29,7 +29,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forConstInstruction();
   }
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 637faf7..9c6b342 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
@@ -8,7 +8,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 
@@ -60,7 +60,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forDebugLocalRead();
   }
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 53791e5..52c8dc6 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
@@ -9,7 +9,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 import com.android.tools.r8.utils.StringUtils;
@@ -100,7 +100,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forDebugLocalsChange();
   }
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 aed2128..5a611aa 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
@@ -9,7 +9,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 
@@ -57,7 +57,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forDebugPosition();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
index 1083669..50fc2ed 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceGet.java
@@ -22,7 +22,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 import org.objectweb.asm.Opcodes;
@@ -114,7 +114,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInstanceGet(field, invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java b/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
index 53fd31c..7a973f8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstanceOf.java
@@ -13,7 +13,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 
@@ -81,7 +81,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInstanceOf(type, invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
index 3585348..e8d917d 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InstancePut.java
@@ -19,7 +19,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.Arrays;
 import org.objectweb.asm.Opcodes;
@@ -113,7 +113,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInstancePut(field, invocationContext);
   }
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 eb85222..d9bf8d0 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
@@ -16,7 +16,7 @@
 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.Constraint;
+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.utils.CfgPrinter;
@@ -1059,7 +1059,7 @@
    *
    * <p>The type is used to judge visibility constraints and also for dispatch decisions.
    */
-  public abstract Constraint inliningConstraint(
+  public abstract ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext);
 
   public abstract void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper);
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
index a6e6fd1..c12333a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeCustom.java
@@ -11,7 +11,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.List;
 
@@ -101,7 +101,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeCustom();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
index 88716dc..46d2e5a 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeDirect.java
@@ -12,7 +12,7 @@
 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.Constraint;
+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.Collection;
@@ -113,7 +113,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeDirect(getInvokedMethod(), invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
index 06d368d..5f49322 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeInterface.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.ir.analysis.type.TypeEnvironment;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+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.Collection;
@@ -95,7 +95,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeInterface(getInvokedMethod(), invocationContext);
   }
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 e34d25f..821d707 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
@@ -12,7 +12,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.List;
 import java.util.function.Function;
@@ -69,7 +69,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeMultiNewArray(type, invocationContext);
   }
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 a2a9c36..17f36df 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
@@ -13,7 +13,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.List;
 import java.util.function.Function;
@@ -99,7 +99,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeNewArray(type, invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
index 8f90630..b45e984 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokePolymorphic.java
@@ -13,7 +13,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.ir.optimize.InliningOracle;
@@ -126,7 +126,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokePolymorphic(getInvokedMethod(), invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
index d2183c0..93660c7 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeStatic.java
@@ -11,7 +11,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.Inliner.InlineAction;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.ir.optimize.InliningOracle;
@@ -103,7 +103,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeStatic(getInvokedMethod(), invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
index 920d94b..141d4d9 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeSuper.java
@@ -13,7 +13,7 @@
 import com.android.tools.r8.ir.analysis.type.TypeEnvironment;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+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.Collection;
@@ -112,7 +112,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeSuper(getInvokedMethod(), invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
index f55a407..51bed08 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InvokeVirtual.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.ir.analysis.type.TypeEnvironment;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+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.Collection;
@@ -95,7 +95,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forInvokeVirtual(getInvokedMethod(), invocationContext);
   }
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 6096292..ded6002 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,7 +4,7 @@
 package com.android.tools.r8.ir.code;
 
 import com.android.tools.r8.graph.DexType;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 import java.util.List;
@@ -47,7 +47,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forJumpInstruction();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Load.java b/src/main/java/com/android/tools/r8/ir/code/Load.java
index 32654b8..5981249 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Load.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Load.java
@@ -11,7 +11,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 
 public class Load extends Instruction {
@@ -51,7 +51,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forLoad();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Monitor.java b/src/main/java/com/android/tools/r8/ir/code/Monitor.java
index 3b1b2d1..70af068 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Monitor.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Monitor.java
@@ -14,7 +14,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 
 public class Monitor extends Instruction {
@@ -97,7 +97,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forMonitor();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Move.java b/src/main/java/com/android/tools/r8/ir/code/Move.java
index e474bb8..6223501 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Move.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Move.java
@@ -12,7 +12,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 
@@ -100,7 +100,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forMove();
   }
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 eabf7b2..e7d6e63 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
@@ -12,7 +12,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 import java.util.HashSet;
@@ -75,7 +75,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forMoveException();
   }
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 edca979..69867e6 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
@@ -13,7 +13,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 
@@ -84,7 +84,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forNewArrayEmpty(type, invocationContext);
   }
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 ac46cc7..8dac404 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
@@ -11,7 +11,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 import java.util.Arrays;
@@ -112,7 +112,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forNewArrayFilledData();
   }
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 75931ad..92e7f3e 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
@@ -12,7 +12,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 
@@ -81,7 +81,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forNewInstance(clazz, invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/NonNull.java b/src/main/java/com/android/tools/r8/ir/code/NonNull.java
index 462af06..d909144 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NonNull.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NonNull.java
@@ -10,7 +10,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 
@@ -85,7 +85,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forNonNull();
   }
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 0fb1949..8ea55dd 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
@@ -9,7 +9,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 
@@ -50,7 +50,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forPop();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Return.java b/src/main/java/com/android/tools/r8/ir/code/Return.java
index 37cfaf0..bb750c2 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Return.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Return.java
@@ -15,7 +15,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 
 public class Return extends JumpInstruction {
@@ -116,7 +116,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forReturn();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
index 486f9e2..108beee 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticGet.java
@@ -21,7 +21,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 import org.objectweb.asm.Opcodes;
@@ -109,7 +109,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forStaticGet(field, invocationContext);
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
index f910ff6..8824d54 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StaticPut.java
@@ -18,7 +18,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import org.objectweb.asm.Opcodes;
 
@@ -107,7 +107,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forStaticPut(field, invocationContext);
   }
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 b81af69..cec5501 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
@@ -12,7 +12,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.utils.InternalOptions;
 
@@ -53,7 +53,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forStore();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Throw.java b/src/main/java/com/android/tools/r8/ir/code/Throw.java
index 4295dbe..7bda1c8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Throw.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Throw.java
@@ -9,7 +9,7 @@
 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.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 
 public class Throw extends JumpInstruction {
@@ -65,7 +65,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forThrow();
   }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Unop.java b/src/main/java/com/android/tools/r8/ir/code/Unop.java
index 2f6ed7f..b29afd0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Unop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Unop.java
@@ -9,7 +9,7 @@
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.ir.analysis.type.PrimitiveTypeLatticeElement;
 import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import java.util.function.Function;
 
@@ -48,7 +48,7 @@
   }
 
   @Override
-  public Constraint inliningConstraint(
+  public ConstraintWithTarget inliningConstraint(
       InliningConstraints inliningConstraints, DexType invocationContext) {
     return inliningConstraints.forUnop();
   }
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 58e22b7..00c3754 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
@@ -42,7 +42,7 @@
 import com.android.tools.r8.ir.optimize.DeadCodeRemover;
 import com.android.tools.r8.ir.optimize.Devirtualizer;
 import com.android.tools.r8.ir.optimize.Inliner;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.MemberValuePropagation;
 import com.android.tools.r8.ir.optimize.NonNullTracker;
 import com.android.tools.r8.ir.optimize.Outliner;
@@ -607,7 +607,7 @@
       rewriteCode(method, feedback, isProcessedConcurrently, callSiteInformation, outlineHandler);
     } else {
       // Mark abstract methods as processed as well.
-      method.markProcessed(Constraint.NEVER);
+      method.markProcessed(ConstraintWithTarget.NEVER);
     }
   }
 
@@ -634,12 +634,12 @@
           method.toSourceString(), logCode(options, method));
     }
     if (options.skipIR) {
-      feedback.markProcessed(method, Constraint.NEVER);
+      feedback.markProcessed(method, ConstraintWithTarget.NEVER);
       return;
     }
     IRCode code = method.buildIR(appInfo, options, appInfo.originFor(method.method.holder));
     if (code == null) {
-      feedback.markProcessed(method, Constraint.NEVER);
+      feedback.markProcessed(method, ConstraintWithTarget.NEVER);
       return;
     }
     if (Log.ENABLED) {
@@ -883,9 +883,9 @@
 
   private void markProcessed(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
     // After all the optimizations have take place, we compute whether method should be inlinedex.
-    Constraint state;
+    ConstraintWithTarget state;
     if (!options.enableInlining || inliner == null) {
-      state = Constraint.NEVER;
+      state = ConstraintWithTarget.NEVER;
     } else {
       state = inliner.computeInliningConstraint(code, method);
     }
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedback.java b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedback.java
index 49bfac8..0833579 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedback.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedback.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.graph.DexEncodedMethod.ClassInlinerEligibility;
 import com.android.tools.r8.graph.ParameterUsagesInfo;
 import com.android.tools.r8.graph.DexEncodedMethod.TrivialInitializer;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import java.util.BitSet;
 
 public interface OptimizationFeedback {
@@ -16,7 +16,7 @@
   void methodReturnsConstant(DexEncodedMethod method, long value);
   void methodNeverReturnsNull(DexEncodedMethod method);
   void methodNeverReturnsNormally(DexEncodedMethod method);
-  void markProcessed(DexEncodedMethod method, Constraint state);
+  void markProcessed(DexEncodedMethod method, ConstraintWithTarget state);
   void markCheckNullReceiverBeforeAnySideEffect(DexEncodedMethod method, boolean mark);
   void markTriggerClassInitBeforeAnySideEffect(DexEncodedMethod method, boolean mark);
   void setClassInlinerEligibility(DexEncodedMethod method, ClassInlinerEligibility eligibility);
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackDirect.java b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackDirect.java
index 1d7a2d6..16267f6 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackDirect.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackDirect.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.graph.DexEncodedMethod.ClassInlinerEligibility;
 import com.android.tools.r8.graph.ParameterUsagesInfo;
 import com.android.tools.r8.graph.DexEncodedMethod.TrivialInitializer;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import java.util.BitSet;
 
 public class OptimizationFeedbackDirect implements OptimizationFeedback {
@@ -34,7 +34,7 @@
   }
 
   @Override
-  public void markProcessed(DexEncodedMethod method, Constraint state) {
+  public void markProcessed(DexEncodedMethod method, ConstraintWithTarget state) {
     method.markProcessed(state);
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackIgnore.java b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackIgnore.java
index 2fb2969..a27f200 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackIgnore.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackIgnore.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.graph.DexEncodedMethod.ClassInlinerEligibility;
 import com.android.tools.r8.graph.ParameterUsagesInfo;
 import com.android.tools.r8.graph.DexEncodedMethod.TrivialInitializer;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import java.util.BitSet;
 
 public class OptimizationFeedbackIgnore implements OptimizationFeedback {
@@ -26,7 +26,7 @@
   public void methodNeverReturnsNormally(DexEncodedMethod method) {}
 
   @Override
-  public void markProcessed(DexEncodedMethod method, Constraint state) {}
+  public void markProcessed(DexEncodedMethod method, ConstraintWithTarget state) {}
 
   @Override
   public void markCheckNullReceiverBeforeAnySideEffect(DexEncodedMethod method, boolean mark) {}
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackSimple.java b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackSimple.java
index b31f28a..2583f8f 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackSimple.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/OptimizationFeedbackSimple.java
@@ -8,7 +8,7 @@
 import com.android.tools.r8.graph.DexEncodedMethod.ClassInlinerEligibility;
 import com.android.tools.r8.graph.DexEncodedMethod.TrivialInitializer;
 import com.android.tools.r8.graph.ParameterUsagesInfo;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import java.util.BitSet;
 
 public class OptimizationFeedbackSimple implements OptimizationFeedback {
@@ -34,9 +34,9 @@
   }
 
   @Override
-  public void markProcessed(DexEncodedMethod method, Constraint state) {
+  public void markProcessed(DexEncodedMethod method, ConstraintWithTarget state) {
     // Just as processed, don't provide any inlining constraints.
-    method.markProcessed(Constraint.NEVER);
+    method.markProcessed(ConstraintWithTarget.NEVER);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
index e6de678..eb3511b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Devirtualizer.java
@@ -18,7 +18,7 @@
 import com.android.tools.r8.ir.code.InvokeVirtual;
 import com.android.tools.r8.ir.code.NonNull;
 import com.android.tools.r8.ir.code.Value;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -86,8 +86,9 @@
           continue;
         }
         // Due to the potential downcast below, make sure the new target holder is visible.
-        Constraint visibility = Constraint.classIsVisible(invocationContext, holderType, appInfo);
-        if (visibility == Constraint.NEVER) {
+        ConstraintWithTarget visibility =
+            ConstraintWithTarget.classIsVisible(invocationContext, holderType, appInfo);
+        if (visibility == ConstraintWithTarget.NEVER) {
           continue;
         }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
index db674bd..283716b 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Inliner.java
@@ -74,27 +74,30 @@
     return blackList.contains(method.method) || appInfo.neverInline.contains(method);
   }
 
-  private Constraint instructionAllowedForInlining(
+  private ConstraintWithTarget instructionAllowedForInlining(
       Instruction instruction, InliningConstraints inliningConstraints, DexType invocationContext) {
-    Constraint result = instruction.inliningConstraint(inliningConstraints, invocationContext);
-    if (result == Constraint.NEVER && instruction.isDebugInstruction()) {
-      return Constraint.ALWAYS;
+    ConstraintWithTarget result =
+        instruction.inliningConstraint(inliningConstraints, invocationContext);
+    if (result == ConstraintWithTarget.NEVER && instruction.isDebugInstruction()) {
+      return ConstraintWithTarget.ALWAYS;
     }
     return result;
   }
 
-  public Constraint computeInliningConstraint(IRCode code, DexEncodedMethod method) {
-    Constraint result = Constraint.ALWAYS;
+  public ConstraintWithTarget computeInliningConstraint(IRCode code, DexEncodedMethod method) {
+    ConstraintWithTarget result = ConstraintWithTarget.ALWAYS;
     InliningConstraints inliningConstraints = new InliningConstraints(appInfo);
     InstructionIterator it = code.instructionIterator();
     while (it.hasNext()) {
       Instruction instruction = it.next();
-      Constraint state =
+      ConstraintWithTarget state =
           instructionAllowedForInlining(instruction, inliningConstraints, method.method.holder);
-      result = Constraint.min(result, state);
-      if (result == Constraint.NEVER) {
+      if (state == ConstraintWithTarget.NEVER) {
+        result = state;
         break;
       }
+      // TODO(b/111080693): we may need to collect all meaningful constraints.
+      result = ConstraintWithTarget.min(result, state, appInfo);
     }
     return result;
   }
@@ -178,8 +181,8 @@
     // The ordinal values are important so please do not reorder.
     NEVER,     // Never inline this.
     SAMECLASS, // Only inline this into methods with same holder.
-    PACKAGE,   // Only inline this into methods with holders from same package.
-    SUBCLASS,  // Only inline this into methods with holders from a subclass.
+    PACKAGE,   // Only inline this into methods with holders from the same package.
+    SUBCLASS,  // Only inline this into methods with holders from a subclass in a different package.
     ALWAYS;    // No restrictions for inlining this.
 
     static {
@@ -189,7 +192,67 @@
       assert SUBCLASS.ordinal() < ALWAYS.ordinal();
     }
 
-    public static Constraint deriveConstraint(
+    static Constraint min(Constraint one, Constraint other) {
+      return one.ordinal() < other.ordinal() ? one : other;
+    }
+  }
+
+  /**
+   * Encodes the constraints for inlining, along with the target holder.
+   * <p>
+   * Constraint itself cannot determine whether or not the method can be inlined if instructions in
+   * the method have different constraints with different targets. For example,
+   *   SUBCLASS of x.A v.s. PACKAGE of y.B
+   * Without any target holder information, min of those two Constraints is PACKAGE, meaning that
+   * the current method can be inlined to any method whose holder is in package y. This could cause
+   * an illegal access error due to protect members in x.A. Because of different target holders,
+   * those constraints should not be combined.
+   * <p>
+   * Instead, a right constraint for inlining constraint for the example above is: a method whose
+   * holder is a subclass of x.A _and_ in the same package of y.B can inline this method.
+   */
+  public static class ConstraintWithTarget {
+    public final Constraint constraint;
+    // Note that this is not context---where this constraint is encoded.
+    // It literally refers to the holder type of the target, which could be:
+    // invoked method in invocations, field in field instructions, type of check-cast, etc.
+    final DexType targetHolder;
+
+    public static final ConstraintWithTarget NEVER = new ConstraintWithTarget(Constraint.NEVER);
+    public static final ConstraintWithTarget ALWAYS = new ConstraintWithTarget(Constraint.ALWAYS);
+
+    private ConstraintWithTarget(Constraint constraint) {
+      assert constraint == Constraint.NEVER || constraint == Constraint.ALWAYS;
+      this.constraint = constraint;
+      this.targetHolder = null;
+    }
+
+    ConstraintWithTarget(Constraint constraint, DexType targetHolder) {
+      assert constraint != Constraint.NEVER && constraint != Constraint.ALWAYS;
+      assert targetHolder != null;
+      this.constraint = constraint;
+      this.targetHolder = targetHolder;
+    }
+
+    @Override
+    public int hashCode() {
+      if (targetHolder == null) {
+        return constraint.ordinal();
+      }
+      return constraint.ordinal() * targetHolder.computeHashCode();
+    }
+
+    @Override
+    public boolean equals(Object other) {
+      if (!(other instanceof ConstraintWithTarget)) {
+        return false;
+      }
+      ConstraintWithTarget o = (ConstraintWithTarget) other;
+      return this.constraint.ordinal() == o.constraint.ordinal()
+          && this.targetHolder == o.targetHolder;
+    }
+
+    public static ConstraintWithTarget deriveConstraint(
         DexType contextHolder,
         DexType targetHolder,
         AccessFlags flags,
@@ -197,23 +260,25 @@
       if (flags.isPublic()) {
         return ALWAYS;
       } else if (flags.isPrivate()) {
-        return targetHolder == contextHolder ? SAMECLASS : NEVER;
+        return targetHolder == contextHolder
+            ? new ConstraintWithTarget(Constraint.SAMECLASS, targetHolder) : NEVER;
       } else if (flags.isProtected()) {
         if (targetHolder.isSamePackage(contextHolder)) {
           // Even though protected, this is visible via the same package from the context.
-          return PACKAGE;
+          return new ConstraintWithTarget(Constraint.PACKAGE, targetHolder);
         } else if (contextHolder.isSubtypeOf(targetHolder, appInfo)) {
-          return SUBCLASS;
+          return new ConstraintWithTarget(Constraint.SUBCLASS, targetHolder);
         }
         return NEVER;
       } else {
         /* package-private */
-        return targetHolder.isSamePackage(contextHolder) ? PACKAGE : NEVER;
+        return targetHolder.isSamePackage(contextHolder)
+            ? new ConstraintWithTarget(Constraint.PACKAGE, targetHolder) : NEVER;
       }
     }
 
-    public static Constraint classIsVisible(DexType context, DexType clazz,
-        AppInfoWithSubtyping appInfo) {
+    public static ConstraintWithTarget classIsVisible(
+        DexType context, DexType clazz, AppInfoWithSubtyping appInfo) {
       if (clazz.isArrayType()) {
         return classIsVisible(context, clazz.toArrayElementType(appInfo.dexItemFactory), appInfo);
       }
@@ -227,8 +292,76 @@
           : deriveConstraint(context, clazz, definition.accessFlags, appInfo);
     }
 
-    public static Constraint min(Constraint one, Constraint other) {
-      return one.ordinal() < other.ordinal() ? one : other;
+    public static ConstraintWithTarget min(
+        ConstraintWithTarget one, ConstraintWithTarget other, AppInfoWithSubtyping appInfo) {
+      if (one.equals(other)) {
+        return one;
+      }
+      if (one == NEVER || other == NEVER) {
+        return NEVER;
+      }
+      if (other.constraint.ordinal() < one.constraint.ordinal()) {
+        return min(other, one, appInfo);
+      }
+      // From now on, one.constraint.ordinal() <= other.constraint.ordinal()
+      if (other == ALWAYS) {
+        return one;
+      }
+      Constraint minConstraint = Constraint.min(one.constraint, other.constraint);
+      assert minConstraint != Constraint.NEVER;
+      assert minConstraint != Constraint.ALWAYS;
+      // SAMECLASS <= SAMECLASS, PACKAGE, SUBCLASS
+      if (minConstraint == Constraint.SAMECLASS) {
+        assert one.constraint == Constraint.SAMECLASS;
+        if (other.constraint == Constraint.SAMECLASS) {
+          assert one.targetHolder != other.targetHolder;
+          return NEVER;
+        }
+        if (other.constraint == Constraint.PACKAGE) {
+          if (one.targetHolder.isSamePackage(other.targetHolder)) {
+            return one;
+          }
+          return NEVER;
+        }
+        assert other.constraint == Constraint.SUBCLASS;
+        if (one.targetHolder.isSubtypeOf(other.targetHolder, appInfo)) {
+          return one;
+        }
+        return NEVER;
+      }
+      // PACKAGE <= PACKAGE, SUBCLASS
+      if (minConstraint == Constraint.PACKAGE) {
+        assert one.constraint == Constraint.PACKAGE;
+        if (other.constraint == Constraint.PACKAGE) {
+          assert one.targetHolder != other.targetHolder;
+          if (one.targetHolder.isSamePackage(other.targetHolder)) {
+            return one;
+          }
+          // PACKAGE of x and PACKAGE of y can be satisfied together.
+          return NEVER;
+        }
+        assert other.constraint == Constraint.SUBCLASS;
+        if (other.targetHolder.isSamePackage(one.targetHolder)) {
+          // Then, PACKAGE is more restrictive constraint.
+          return one;
+        }
+        // TODO(b/111080693): towards finer-grained constraints, we need both.
+        // Even though they're in different package, it is still inlinable to a class that is
+        // in the same package of one's context and a sub type of other's context.
+        return NEVER;
+      }
+      // SUBCLASS <= SUBCLASS
+      assert minConstraint == Constraint.SUBCLASS;
+      assert one.constraint == other.constraint;
+      assert one.targetHolder != other.targetHolder;
+      if (one.targetHolder.isSubtypeOf(other.targetHolder, appInfo)) {
+        return one;
+      }
+      if (other.targetHolder.isSubtypeOf(one.targetHolder, appInfo)) {
+        return other;
+      }
+      // SUBCLASS of x and SUBCLASS of y while x and y are not a subtype of each other.
+      return NEVER;
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
index 073d6ae..fe10637 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/InliningConstraints.java
@@ -15,6 +15,7 @@
 import com.android.tools.r8.graph.GraphLense;
 import com.android.tools.r8.ir.code.Invoke.Type;
 import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import java.util.Collection;
 
@@ -45,71 +46,71 @@
     this.graphLense = graphLense;
   }
 
-  public Constraint forAlwaysMaterializingUser() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forAlwaysMaterializingUser() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forArgument() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forArgument() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forArrayGet() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forArrayGet() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forArrayLength() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forArrayLength() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forArrayPut() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forArrayPut() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forBinop() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forBinop() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forCheckCast(DexType type, DexType invocationContext) {
-    return Constraint.classIsVisible(invocationContext, type, appInfo);
+  public ConstraintWithTarget forCheckCast(DexType type, DexType invocationContext) {
+    return ConstraintWithTarget.classIsVisible(invocationContext, type, appInfo);
   }
 
-  public Constraint forConstClass(DexType type, DexType invocationContext) {
-    return Constraint.classIsVisible(invocationContext, type, appInfo);
+  public ConstraintWithTarget forConstClass(DexType type, DexType invocationContext) {
+    return ConstraintWithTarget.classIsVisible(invocationContext, type, appInfo);
   }
 
-  public Constraint forConstInstruction() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forConstInstruction() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forDebugLocalRead() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forDebugLocalRead() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forDebugLocalsChange() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forDebugLocalsChange() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forDebugPosition() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forDebugPosition() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forInstanceGet(DexField field, DexType invocationContext) {
+  public ConstraintWithTarget forInstanceGet(DexField field, DexType invocationContext) {
     DexField lookup = graphLense.lookupField(field);
     return forFieldInstruction(
         lookup, appInfo.lookupInstanceTarget(lookup.clazz, lookup), invocationContext);
   }
 
-  public Constraint forInstanceOf(DexType type, DexType invocationContext) {
-    return Constraint.classIsVisible(invocationContext, type, appInfo);
+  public ConstraintWithTarget forInstanceOf(DexType type, DexType invocationContext) {
+    return ConstraintWithTarget.classIsVisible(invocationContext, type, appInfo);
   }
 
-  public Constraint forInstancePut(DexField field, DexType invocationContext) {
+  public ConstraintWithTarget forInstancePut(DexField field, DexType invocationContext) {
     DexField lookup = graphLense.lookupField(field);
     return forFieldInstruction(
         lookup, appInfo.lookupInstanceTarget(lookup.clazz, lookup), invocationContext);
   }
 
-  public Constraint forInvoke(DexMethod method, Type type, DexType invocationContext) {
+  public ConstraintWithTarget forInvoke(DexMethod method, Type type, DexType invocationContext) {
     switch (type) {
       case DIRECT:
         return forInvokeDirect(method, invocationContext);
@@ -130,162 +131,165 @@
     }
   }
 
-  public Constraint forInvokeCustom() {
-    return Constraint.NEVER;
+  public ConstraintWithTarget forInvokeCustom() {
+    return ConstraintWithTarget.NEVER;
   }
 
-  public Constraint forInvokeDirect(DexMethod method, DexType invocationContext) {
+  public ConstraintWithTarget forInvokeDirect(DexMethod method, DexType invocationContext) {
     DexMethod lookup = graphLense.lookupMethod(method);
     return forSingleTargetInvoke(lookup, appInfo.lookupDirectTarget(lookup), invocationContext);
   }
 
-  public Constraint forInvokeInterface(DexMethod method, DexType invocationContext) {
+  public ConstraintWithTarget forInvokeInterface(DexMethod method, DexType invocationContext) {
     DexMethod lookup = graphLense.lookupMethod(method);
     return forVirtualInvoke(lookup, appInfo.lookupInterfaceTargets(lookup), invocationContext);
   }
 
-  public Constraint forInvokeMultiNewArray(DexType type, DexType invocationContext) {
-    return Constraint.classIsVisible(invocationContext, type, appInfo);
+  public ConstraintWithTarget forInvokeMultiNewArray(DexType type, DexType invocationContext) {
+    return ConstraintWithTarget.classIsVisible(invocationContext, type, appInfo);
   }
 
-  public Constraint forInvokeNewArray(DexType type, DexType invocationContext) {
-    return Constraint.classIsVisible(invocationContext, type, appInfo);
+  public ConstraintWithTarget forInvokeNewArray(DexType type, DexType invocationContext) {
+    return ConstraintWithTarget.classIsVisible(invocationContext, type, appInfo);
   }
 
-  public Constraint forInvokePolymorphic(DexMethod method, DexType invocationContext) {
-    return Constraint.NEVER;
+  public ConstraintWithTarget forInvokePolymorphic(DexMethod method, DexType invocationContext) {
+    return ConstraintWithTarget.NEVER;
   }
 
-  public Constraint forInvokeStatic(DexMethod method, DexType invocationContext) {
+  public ConstraintWithTarget forInvokeStatic(DexMethod method, DexType invocationContext) {
     DexMethod lookup = graphLense.lookupMethod(method);
     return forSingleTargetInvoke(lookup, appInfo.lookupStaticTarget(lookup), invocationContext);
   }
 
-  public Constraint forInvokeSuper(DexMethod method, DexType invocationContext) {
+  public ConstraintWithTarget forInvokeSuper(DexMethod method, DexType invocationContext) {
     // The semantics of invoke super depend on the context.
-    return Constraint.SAMECLASS;
+    return new ConstraintWithTarget(Constraint.SAMECLASS, invocationContext);
   }
 
-  public Constraint forInvokeVirtual(DexMethod method, DexType invocationContext) {
+  public ConstraintWithTarget forInvokeVirtual(DexMethod method, DexType invocationContext) {
     DexMethod lookup = graphLense.lookupMethod(method);
     return forVirtualInvoke(lookup, appInfo.lookupVirtualTargets(lookup), invocationContext);
   }
 
-  public Constraint forJumpInstruction() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forJumpInstruction() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forLoad() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forLoad() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forMonitor() {
+  public ConstraintWithTarget forMonitor() {
     // Conservative choice.
-    return Constraint.NEVER;
+    return ConstraintWithTarget.NEVER;
   }
 
-  public Constraint forMove() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forMove() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forMoveException() {
+  public ConstraintWithTarget forMoveException() {
     // TODO(64432527): Revisit this constraint.
-    return Constraint.NEVER;
+    return ConstraintWithTarget.NEVER;
   }
 
-  public Constraint forNewArrayEmpty(DexType type, DexType invocationContext) {
-    return Constraint.classIsVisible(invocationContext, type, appInfo);
+  public ConstraintWithTarget forNewArrayEmpty(DexType type, DexType invocationContext) {
+    return ConstraintWithTarget.classIsVisible(invocationContext, type, appInfo);
   }
 
-  public Constraint forNewArrayFilledData() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forNewArrayFilledData() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forNewInstance(DexType type, DexType invocationContext) {
-    return Constraint.classIsVisible(invocationContext, type, appInfo);
+  public ConstraintWithTarget forNewInstance(DexType type, DexType invocationContext) {
+    return ConstraintWithTarget.classIsVisible(invocationContext, type, appInfo);
   }
 
-  public Constraint forNonNull() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forNonNull() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forPop() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forPop() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forReturn() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forReturn() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forStaticGet(DexField field, DexType invocationContext) {
+  public ConstraintWithTarget forStaticGet(DexField field, DexType invocationContext) {
     DexField lookup = graphLense.lookupField(field);
     return forFieldInstruction(
         lookup, appInfo.lookupStaticTarget(lookup.clazz, lookup), invocationContext);
   }
 
-  public Constraint forStaticPut(DexField field, DexType invocationContext) {
+  public ConstraintWithTarget forStaticPut(DexField field, DexType invocationContext) {
     DexField lookup = graphLense.lookupField(field);
     return forFieldInstruction(
         lookup, appInfo.lookupStaticTarget(lookup.clazz, lookup), invocationContext);
   }
 
-  public Constraint forStore() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forStore() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forThrow() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forThrow() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint forUnop() {
-    return Constraint.ALWAYS;
+  public ConstraintWithTarget forUnop() {
+    return ConstraintWithTarget.ALWAYS;
   }
 
-  private Constraint forFieldInstruction(
+  private ConstraintWithTarget forFieldInstruction(
       DexField field, DexEncodedField target, DexType invocationContext) {
     // Resolve the field if possible and decide whether the instruction can inlined.
     DexType fieldHolder = graphLense.lookupType(field.clazz);
     DexClass fieldClass = appInfo.definitionFor(fieldHolder);
     if (target != null && fieldClass != null) {
-      Constraint fieldConstraint =
-          Constraint.deriveConstraint(invocationContext, fieldHolder, target.accessFlags, appInfo);
-      Constraint classConstraint =
-          Constraint.deriveConstraint(
+      ConstraintWithTarget fieldConstraintWithTarget =
+          ConstraintWithTarget.deriveConstraint(
+              invocationContext, fieldHolder, target.accessFlags, appInfo);
+      ConstraintWithTarget classConstraintWithTarget =
+          ConstraintWithTarget.deriveConstraint(
               invocationContext, fieldHolder, fieldClass.accessFlags, appInfo);
-      return Constraint.min(fieldConstraint, classConstraint);
+      return ConstraintWithTarget.min(
+          fieldConstraintWithTarget, classConstraintWithTarget, appInfo);
     }
-    return Constraint.NEVER;
+    return ConstraintWithTarget.NEVER;
   }
 
-  private Constraint forSingleTargetInvoke(
+  private ConstraintWithTarget forSingleTargetInvoke(
       DexMethod method, DexEncodedMethod target, DexType invocationContext) {
     if (method.holder.isArrayType()) {
-      return Constraint.ALWAYS;
+      return ConstraintWithTarget.ALWAYS;
     }
     if (target != null) {
       DexType methodHolder = graphLense.lookupType(target.method.holder);
       DexClass methodClass = appInfo.definitionFor(methodHolder);
       if (methodClass != null) {
-        Constraint methodConstraint =
-            Constraint.deriveConstraint(
+        ConstraintWithTarget methodConstraintWithTarget =
+            ConstraintWithTarget.deriveConstraint(
                 invocationContext, methodHolder, target.accessFlags, appInfo);
         // We also have to take the constraint of the enclosing class into account.
-        Constraint classConstraint =
-            Constraint.deriveConstraint(
+        ConstraintWithTarget classConstraintWithTarget =
+            ConstraintWithTarget.deriveConstraint(
                 invocationContext, methodHolder, methodClass.accessFlags, appInfo);
-        return Constraint.min(methodConstraint, classConstraint);
+        return ConstraintWithTarget.min(
+            methodConstraintWithTarget, classConstraintWithTarget, appInfo);
       }
     }
-    return Constraint.NEVER;
+    return ConstraintWithTarget.NEVER;
   }
 
-  private Constraint forVirtualInvoke(
+  private ConstraintWithTarget forVirtualInvoke(
       DexMethod method, Collection<DexEncodedMethod> targets, DexType invocationContext) {
     if (method.holder.isArrayType()) {
-      return Constraint.ALWAYS;
+      return ConstraintWithTarget.ALWAYS;
     }
     if (targets == null) {
-      return Constraint.NEVER;
+      return ConstraintWithTarget.NEVER;
     }
 
     // Perform resolution and derive inlining constraints based on the accessibility of the
@@ -294,25 +298,26 @@
     DexEncodedMethod resolutionTarget = resolutionResult.asResultOfResolve();
     if (resolutionTarget == null) {
       // This will fail at runtime.
-      return Constraint.NEVER;
+      return ConstraintWithTarget.NEVER;
     }
 
     DexType methodHolder = graphLense.lookupType(resolutionTarget.method.holder);
     DexClass methodClass = appInfo.definitionFor(methodHolder);
     assert methodClass != null;
-    Constraint methodConstraint =
-        Constraint.deriveConstraint(
+    ConstraintWithTarget methodConstraintWithTarget =
+        ConstraintWithTarget.deriveConstraint(
             invocationContext, methodHolder, resolutionTarget.accessFlags, appInfo);
     // We also have to take the constraint of the enclosing class of the resolution result
     // into account. We do not allow inlining this method if it is calling something that
     // is inaccessible. Inlining in that case could move the code to another package making a
     // call succeed that should not succeed. Conversely, if the resolution result is accessible,
     // we have to make sure that inlining cannot make it inaccessible.
-    Constraint classConstraint =
-        Constraint.deriveConstraint(
+    ConstraintWithTarget classConstraintWithTarget =
+        ConstraintWithTarget.deriveConstraint(
             invocationContext, methodHolder, methodClass.accessFlags, appInfo);
-    Constraint result = Constraint.min(methodConstraint, classConstraint);
-    if (result == Constraint.NEVER) {
+    ConstraintWithTarget result =
+        ConstraintWithTarget.min(methodConstraintWithTarget, classConstraintWithTarget, appInfo);
+    if (result == ConstraintWithTarget.NEVER) {
       return result;
     }
 
@@ -321,10 +326,11 @@
     for (DexEncodedMethod target : targets) {
       methodHolder = graphLense.lookupType(target.method.holder);
       assert appInfo.definitionFor(methodHolder) != null;
-      methodConstraint =
-          Constraint.deriveConstraint(invocationContext, methodHolder, target.accessFlags, appInfo);
-      result = Constraint.min(result, methodConstraint);
-      if (result == Constraint.NEVER) {
+      methodConstraintWithTarget =
+          ConstraintWithTarget.deriveConstraint(
+              invocationContext, methodHolder, target.accessFlags, appInfo);
+      result = ConstraintWithTarget.min(result, methodConstraintWithTarget, appInfo);
+      if (result == ConstraintWithTarget.NEVER) {
         return result;
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
index 6f3a0f5..505d192 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/Outliner.java
@@ -44,7 +44,7 @@
 import com.android.tools.r8.ir.code.ValueType;
 import com.android.tools.r8.ir.conversion.IRBuilder;
 import com.android.tools.r8.ir.conversion.SourceCode;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.naming.ClassNameMapper;
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.origin.SynthesizedOrigin;
@@ -476,8 +476,9 @@
 
       // See whether we could move this invoke somewhere else. We reuse the logic from inlining
       // here, as the constraints are the same.
-      Constraint constraint = invoke.inliningConstraint(inliningConstraints, method.method.holder);
-      if (constraint != Constraint.ALWAYS) {
+      ConstraintWithTarget constraint =
+          invoke.inliningConstraint(inliningConstraints, method.method.holder);
+      if (constraint != ConstraintWithTarget.ALWAYS) {
         return false;
       }
       // Find the number of in-going arguments, if adding this instruction.
diff --git a/src/main/java/com/android/tools/r8/jar/InliningConstraintVisitor.java b/src/main/java/com/android/tools/r8/jar/InliningConstraintVisitor.java
index 459d7de..dbc48a3 100644
--- a/src/main/java/com/android/tools/r8/jar/InliningConstraintVisitor.java
+++ b/src/main/java/com/android/tools/r8/jar/InliningConstraintVisitor.java
@@ -17,7 +17,7 @@
 import com.android.tools.r8.graph.JarApplicationReader;
 import com.android.tools.r8.ir.code.Invoke;
 import com.android.tools.r8.ir.conversion.JarSourceCode;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+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 org.objectweb.asm.MethodVisitor;
@@ -40,7 +40,7 @@
   private final DexEncodedMethod method;
   private final DexType invocationContext;
 
-  private Constraint constraint;
+  private ConstraintWithTarget constraint;
 
   public InliningConstraintVisitor(
       JarApplicationReader application,
@@ -58,22 +58,22 @@
     this.invocationContext = invocationContext;
 
     // Model a synchronized method as having a monitor instruction.
-    this.constraint =
-        method.accessFlags.isSynchronized() ? inliningConstraints.forMonitor() : Constraint.ALWAYS;
+    this.constraint = method.accessFlags.isSynchronized()
+        ? inliningConstraints.forMonitor() : ConstraintWithTarget.ALWAYS;
   }
 
-  public Constraint getConstraint() {
+  public ConstraintWithTarget getConstraint() {
     return constraint;
   }
 
-  private void updateConstraint(Constraint other) {
-    constraint = Constraint.min(constraint, other);
+  private void updateConstraint(ConstraintWithTarget other) {
+    constraint = ConstraintWithTarget.min(constraint, other, appInfo);
   }
 
   // Used to signal that the result is ready, such that we do not need to visit all instructions of
   // the method, if we can see early on that it cannot be inlined anyway.
   public boolean isFinished() {
-    return constraint == Constraint.NEVER;
+    return constraint == ConstraintWithTarget.NEVER;
   }
 
   public void accept(TryCatchBlockNode tryCatchBlock) {
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index fe098cc..c1d7403 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -12,7 +12,7 @@
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.GraphLense;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.shaking.Enqueuer.AppInfoWithLiveness;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
@@ -208,14 +208,14 @@
     if (holder == null) {
       return false;
     }
-    Constraint classVisibility =
-        Constraint.deriveConstraint(context, holderType, holder.accessFlags, appInfo);
-    if (classVisibility == Constraint.NEVER) {
+    ConstraintWithTarget classVisibility =
+        ConstraintWithTarget.deriveConstraint(context, holderType, holder.accessFlags, appInfo);
+    if (classVisibility == ConstraintWithTarget.NEVER) {
       return false;
     }
-    Constraint fieldVisibility =
-        Constraint.deriveConstraint(context, holderType, field.accessFlags, appInfo);
-    return fieldVisibility != Constraint.NEVER;
+    ConstraintWithTarget fieldVisibility =
+        ConstraintWithTarget.deriveConstraint(context, holderType, field.accessFlags, appInfo);
+    return fieldVisibility != ConstraintWithTarget.NEVER;
   }
 
   private Map<DexField, Set<DexEncodedMethod>> mergeFieldAccessContexts(
diff --git a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
index 451b2cb..a19c0d5 100644
--- a/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
+++ b/src/main/java/com/android/tools/r8/shaking/VerticalClassMerger.java
@@ -31,7 +31,7 @@
 import com.android.tools.r8.graph.PresortedComparable;
 import com.android.tools.r8.graph.UseRegistry;
 import com.android.tools.r8.ir.code.Invoke.Type;
-import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.MethodPoolCollection;
 import com.android.tools.r8.ir.optimize.MethodPoolCollection.MethodPool;
 import com.android.tools.r8.ir.synthetic.ForwardMethodSourceCode;
@@ -1486,13 +1486,13 @@
     // that we always return true here in these cases.
     if (method.getCode().isJarCode()) {
       JarCode jarCode = method.getCode().asJarCode();
-      Constraint constraint =
+      ConstraintWithTarget constraint =
           jarCode.computeInliningConstraint(
               method,
               appInfo,
               new SingleTypeMapperGraphLense(method.method.holder, invocationContext),
               invocationContext);
-      return constraint == Constraint.NEVER;
+      return constraint == ConstraintWithTarget.NEVER;
     }
     // TODO(christofferqa): For non-jar code we currently cannot guarantee that markForceInline()
     // will succeed.
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/ConstraintWithTargetTest.java b/src/test/java/com/android/tools/r8/ir/optimize/ConstraintWithTargetTest.java
new file mode 100644
index 0000000..f3dbe46
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/ir/optimize/ConstraintWithTargetTest.java
@@ -0,0 +1,144 @@
+// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.ir.optimize;
+
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.dex.ApplicationReader;
+import com.android.tools.r8.graph.AppInfoWithSubtyping;
+import com.android.tools.r8.graph.DexApplication;
+import com.android.tools.r8.graph.DexItemFactory;
+import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.optimize.Inliner.Constraint;
+import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
+import com.android.tools.r8.utils.AndroidApp;
+import com.android.tools.r8.utils.InternalOptions;
+import com.android.tools.r8.utils.Timing;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ConstraintWithTargetTest {
+  private static DexItemFactory factory;
+  private static AppInfoWithSubtyping appInfo;
+
+  @BeforeClass
+  public static void makeAppInfo() throws Exception {
+    InternalOptions options = new InternalOptions();
+    DexApplication application =
+        new ApplicationReader(
+                AndroidApp.builder()
+                    .addLibraryFiles(ToolHelper.getDefaultAndroidJar())
+                    .build(),
+                options,
+                new Timing(ConstraintWithTargetTest.class.getName()))
+            .read()
+            .toDirect();
+    factory = options.itemFactory;
+    appInfo = new AppInfoWithSubtyping(application);
+  }
+
+  private ConstraintWithTarget never() {
+    return ConstraintWithTarget.NEVER;
+  }
+
+  private ConstraintWithTarget always() {
+    return ConstraintWithTarget.ALWAYS;
+  }
+
+  private ConstraintWithTarget element(Constraint constraint, DexType type) {
+    return new ConstraintWithTarget(constraint, type);
+  }
+
+  private ConstraintWithTarget meet(ConstraintWithTarget e1, ConstraintWithTarget e2) {
+    return ConstraintWithTarget.min(e1, e2, appInfo);
+  }
+
+  @Test
+  public void meetNeverIsNever() {
+    assertEquals(never(),
+        meet(never(), always()));
+    assertEquals(never(),
+        meet(always(), never()));
+    assertEquals(never(),
+        meet(never(), element(Constraint.SAMECLASS, factory.objectType)));
+  }
+
+  @Test
+  public void meetAlwaysIsUnit() {
+    ConstraintWithTarget o = element(Constraint.SUBCLASS, factory.objectType);
+    assertEquals(o,
+        meet(always(), o));
+    assertEquals(o,
+        meet(o, always()));
+  }
+
+  @Test
+  public void withSameTarget() {
+    DexType s = factory.createType("Ljava/lang/String;");
+    ConstraintWithTarget c0 = element(Constraint.SAMECLASS, s);
+    ConstraintWithTarget c1 = element(Constraint.PACKAGE, s);
+    ConstraintWithTarget c2 = element(Constraint.SUBCLASS, s);
+    assertEquals(c0,
+        meet(c1, c0));
+    assertEquals(c0,
+        meet(c0, c2));
+    assertEquals(c1,
+        meet(c2, c1));
+  }
+
+  @Test
+  public void withDifferentTarget() {
+    DexType s = factory.createType("Ljava/lang/String;");
+    DexType b = factory.createType("Ljava/lang/StringBuilder;");
+    ConstraintWithTarget c1 = element(Constraint.SAMECLASS, s);
+    ConstraintWithTarget c2 = element(Constraint.SAMECLASS, b);
+    assertEquals(never(),
+        meet(c1, c2));
+
+    ConstraintWithTarget c0 = element(Constraint.PACKAGE, factory.objectType);
+    assertEquals(c1,
+        meet(c0, c1));
+    assertEquals(c2,
+        meet(c0, c2));
+
+    c0 = element(Constraint.SUBCLASS, factory.objectType);
+    assertEquals(c1,
+        meet(c0, c1));
+    assertEquals(c2,
+        meet(c0, c2));
+
+    c1 = element(Constraint.PACKAGE, s);
+    c2 = element(Constraint.PACKAGE, b);
+    assertEquals(c1,
+        meet(c0, c1));
+    assertEquals(c2,
+        meet(c0, c2));
+    assertEquals(c1,
+        meet(c1, c2));
+    assertEquals(c2,
+        meet(c2, c1));
+
+    DexType t = factory.createType("Ljava/lang/reflect/Type;");
+    DexType c = factory.createType("Ljava/lang/Class;");
+    c1 = element(Constraint.SUBCLASS, t);
+    c2 = element(Constraint.SUBCLASS, c);
+    assertEquals(c2,
+        meet(c1, c2));
+    assertEquals(c2,
+        meet(c2, c1));
+  }
+
+
+  @Test
+  public void b111080693() {
+    ConstraintWithTarget c1 =
+        element(Constraint.SUBCLASS, factory.createType("Ljava/lang/Class;"));
+    ConstraintWithTarget c2 =
+        element(Constraint.PACKAGE, factory.createType("Ljava/lang/reflect/Type;"));
+    assertEquals(never(),
+        meet(c1, c2));
+  }
+
+}
diff --git a/src/test/java/com/android/tools/r8/regress/b111080693/B111080693.java b/src/test/java/com/android/tools/r8/regress/b111080693/B111080693.java
index d424c39..f079016 100644
--- a/src/test/java/com/android/tools/r8/regress/b111080693/B111080693.java
+++ b/src/test/java/com/android/tools/r8/regress/b111080693/B111080693.java
@@ -20,13 +20,11 @@
 import com.android.tools.r8.regress.b111080693.b.RecyclerView;
 import com.android.tools.r8.utils.AndroidApp;
 import com.google.common.collect.ImmutableList;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 @RunWith(VmTestRunner.class)
 public class B111080693 extends TestBase {
-  @Ignore("b/111080693")
   @Test
   public void test() throws Exception {
     R8Command.Builder builder = R8Command.builder();