Extend bytecode metadata to all instructions

Change-Id: I839ae88d3833877e81ab63f006748bc770c4d030
diff --git a/src/main/java/com/android/tools/r8/graph/CfCode.java b/src/main/java/com/android/tools/r8/graph/CfCode.java
index 67eedde..f35751b 100644
--- a/src/main/java/com/android/tools/r8/graph/CfCode.java
+++ b/src/main/java/com/android/tools/r8/graph/CfCode.java
@@ -232,6 +232,11 @@
   }
 
   @Override
+  public BytecodeMetadata<CfInstruction> getMetadata() {
+    return metadata;
+  }
+
+  @Override
   public BytecodeInstructionMetadata getMetadata(CfOrDexInstruction instruction) {
     return getMetadata(instruction.asCfInstruction());
   }
diff --git a/src/main/java/com/android/tools/r8/graph/Code.java b/src/main/java/com/android/tools/r8/graph/Code.java
index e727373..f8d5917 100644
--- a/src/main/java/com/android/tools/r8/graph/Code.java
+++ b/src/main/java/com/android/tools/r8/graph/Code.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.dex.MixedSectionCollection;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.bytecodemetadata.BytecodeInstructionMetadata;
+import com.android.tools.r8.graph.bytecodemetadata.BytecodeMetadata;
 import com.android.tools.r8.ir.code.IRCode;
 import com.android.tools.r8.ir.code.NumberGenerator;
 import com.android.tools.r8.ir.code.Position;
@@ -31,6 +32,10 @@
         + getClass().getCanonicalName());
   }
 
+  public BytecodeMetadata<? extends CfOrDexInstruction> getMetadata() {
+    return null;
+  }
+
   public BytecodeInstructionMetadata getMetadata(CfOrDexInstruction instruction) {
     return null;
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 7689694..a44fc1d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -123,6 +123,11 @@
   }
 
   @Override
+  public BytecodeMetadata<Instruction> getMetadata() {
+    return metadata;
+  }
+
+  @Override
   public BytecodeInstructionMetadata getMetadata(CfOrDexInstruction instruction) {
     return getMetadata(instruction.asDexInstruction());
   }
diff --git a/src/main/java/com/android/tools/r8/graph/bytecodemetadata/BytecodeMetadata.java b/src/main/java/com/android/tools/r8/graph/bytecodemetadata/BytecodeMetadata.java
index ad7dee4..f335b4c 100644
--- a/src/main/java/com/android/tools/r8/graph/bytecodemetadata/BytecodeMetadata.java
+++ b/src/main/java/com/android/tools/r8/graph/bytecodemetadata/BytecodeMetadata.java
@@ -60,5 +60,10 @@
     public BytecodeMetadata<I> build() {
       return backing.isEmpty() ? empty() : new BytecodeMetadata<>(backing);
     }
+
+    public boolean verifyNoMetadata(Instruction irInstruction) {
+      assert bytecodeMetadataProvider.getMetadata(irInstruction) == null;
+      return true;
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
index 45fa439..0e09c04 100644
--- a/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/AlwaysMaterializingNop.java
@@ -42,7 +42,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfNop());
+    builder.add(new CfNop(), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
index bf545a0..a4be195 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ArithmeticBinop.java
@@ -165,6 +165,6 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfArithmeticBinop(getCfOpcode(), type));
+    builder.add(new CfArithmeticBinop(getCfOpcode(), type), this);
   }
 }
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 e1bb5bf..d51e318 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
@@ -176,7 +176,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfArrayLoad(type));
+    builder.add(new CfArrayLoad(type), this);
   }
 
   @Override
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 4f0995b..3835b3d 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
@@ -116,7 +116,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfArrayLength());
+    builder.add(new CfArrayLength(), this);
   }
 
   @Override
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 4108175..9994dde 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
@@ -213,7 +213,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfArrayStore(type));
+    builder.add(new CfArrayStore(type), this);
   }
 
   @Override
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 e34ab51..864e37e 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
@@ -264,7 +264,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfCheckCast(type));
+    builder.add(new CfCheckCast(type), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Cmp.java b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
index 2b44f93..a7b25a3 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Cmp.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Cmp.java
@@ -231,7 +231,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfCmp(bias, type));
+    builder.add(new CfCmp(bias, type), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstClass.java b/src/main/java/com/android/tools/r8/ir/code/ConstClass.java
index 93cefd2..716396d 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
@@ -197,7 +197,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfConstClass(clazz));
+    builder.add(new CfConstClass(clazz), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
index 3973d6e..35cef20 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodHandle.java
@@ -63,7 +63,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfConstMethodHandle(methodHandle));
+    builder.add(new CfConstMethodHandle(methodHandle), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
index 6f153a6..64359c8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstMethodType.java
@@ -63,7 +63,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfConstMethodType(methodType));
+    builder.add(new CfConstMethodType(methodType), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
index b849f75..4111b17 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstNumber.java
@@ -173,9 +173,9 @@
   @Override
   public void buildCf(CfBuilder builder) {
     if (outType().isObject()) {
-      builder.add(new CfConstNull());
+      builder.add(new CfConstNull(), this);
     } else {
-      builder.add(new CfConstNumber(value, outType()));
+      builder.add(new CfConstNumber(value, outType()), this);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/ConstString.java b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
index f873fd8..a3efba8 100644
--- a/src/main/java/com/android/tools/r8/ir/code/ConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/ConstString.java
@@ -144,7 +144,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfConstString(value));
+    builder.add(new CfConstString(value), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java b/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java
index 6817315..ad9be48 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DebugLocalWrite.java
@@ -69,7 +69,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfStore(outType(), builder.getLocalRegister(outValue())));
+    builder.add(new CfStore(outType(), builder.getLocalRegister(outValue())), this);
   }
 
   @Override
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 d4d76da..e5bdb6d 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
@@ -86,7 +86,7 @@
   public void buildCf(CfBuilder builder) {
     assert getPosition().isSome() && !getPosition().isSyntheticPosition();
     // All redundant debug positions are removed. Remaining ones must force a pc advance.
-    builder.add(new CfNop());
+    builder.add(new CfNop(), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
index 4c8c646..4dc3985 100644
--- a/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
+++ b/src/main/java/com/android/tools/r8/ir/code/DexItemBasedConstString.java
@@ -139,7 +139,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfDexItemBasedConstString(item, nameComputationInfo));
+    builder.add(new CfDexItemBasedConstString(item, nameComputationInfo), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup.java b/src/main/java/com/android/tools/r8/ir/code/Dup.java
index 3bdc40c..2c9c3be 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup.java
@@ -69,9 +69,9 @@
   @Override
   public void buildCf(CfBuilder builder) {
     if (this.inValues.get(0).getType().isWidePrimitive()) {
-      builder.add(new CfStackInstruction(Opcode.Dup2));
+      builder.add(new CfStackInstruction(Opcode.Dup2), this);
     } else {
-      builder.add(new CfStackInstruction(Opcode.Dup));
+      builder.add(new CfStackInstruction(Opcode.Dup), this);
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/Dup2.java b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
index a01b789..7eff1c4 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Dup2.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Dup2.java
@@ -86,7 +86,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfStackInstruction(Opcode.Dup2));
+    builder.add(new CfStackInstruction(Opcode.Dup2), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Goto.java b/src/main/java/com/android/tools/r8/ir/code/Goto.java
index dde7f0d..025dec0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Goto.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Goto.java
@@ -118,7 +118,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfGoto(builder.getLabel(getTarget())));
+    builder.add(new CfGoto(builder.getLabel(getTarget())), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/If.java b/src/main/java/com/android/tools/r8/ir/code/If.java
index 62cb5a2..ce75f73 100644
--- a/src/main/java/com/android/tools/r8/ir/code/If.java
+++ b/src/main/java/com/android/tools/r8/ir/code/If.java
@@ -268,11 +268,11 @@
   public void buildCf(CfBuilder builder) {
     ValueType ifType = inValues.get(0).outType();
     if (inValues.size() == 1) {
-      builder.add(new CfIf(type, ifType, builder.getLabel(getTrueTarget())));
+      builder.add(new CfIf(type, ifType, builder.getLabel(getTrueTarget())), this);
       return;
     }
     assert inValues.size() == 2;
     assert inValues.get(0).outType() == inValues.get(1).outType();
-    builder.add(new CfIfCmp(type, ifType, builder.getLabel(getTrueTarget())));
+    builder.add(new CfIfCmp(type, ifType, builder.getLabel(getTrueTarget())), this);
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/Inc.java b/src/main/java/com/android/tools/r8/ir/code/Inc.java
index 3d10cc4..de99253 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Inc.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Inc.java
@@ -83,17 +83,21 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
+    // Check that this instruction does not have any metadata attached, as it might not materialize
+    // as an iinc in CfCode.
+    assert builder.verifyNoMetadata(this);
     Value inValue = inValues.get(0);
     int inRegister = builder.getLocalRegister(inValue);
     int outRegister = builder.getLocalRegister(outValue);
     if (inRegister == outRegister) {
-      builder.add(new CfIinc(inRegister, increment));
+      builder.add(new CfIinc(inRegister, increment), this);
     } else {
       assert inValue.outType() == ValueType.INT;
-      builder.add(new CfLoad(ValueType.INT, inRegister));
-      builder.add(new CfConstNumber(increment, ValueType.INT));
-      builder.add(new CfArithmeticBinop(Opcode.Add, NumericType.INT));
-      builder.add(new CfStore(ValueType.INT, outRegister));
+      builder.add(
+          new CfLoad(ValueType.INT, inRegister),
+          new CfConstNumber(increment, ValueType.INT),
+          new CfArithmeticBinop(Opcode.Add, NumericType.INT),
+          new CfStore(ValueType.INT, outRegister));
     }
   }
 
diff --git a/src/main/java/com/android/tools/r8/ir/code/InitClass.java b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
index aceeab3..80351a6 100644
--- a/src/main/java/com/android/tools/r8/ir/code/InitClass.java
+++ b/src/main/java/com/android/tools/r8/ir/code/InitClass.java
@@ -76,7 +76,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInitClass(clazz));
+    builder.add(new CfInitClass(clazz), this);
   }
 
   @Override
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 0530403..123eb45 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
@@ -109,7 +109,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInstanceOf(type));
+    builder.add(new CfInstanceOf(type), this);
   }
 
   @Override
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 95086dc..13cba81 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
@@ -241,7 +241,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInstanceFieldWrite(getField(), builder.resolveField(getField())));
+    builder.add(new CfInstanceFieldWrite(getField(), builder.resolveField(getField())), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java b/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java
index e0e3cdc..601f67f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IntSwitch.java
@@ -311,12 +311,12 @@
         }
       }
       assert index == numberOfKeys();
-      builder.add(new CfSwitch(Kind.TABLE, fallthroughLabel, new int[] {min}, labels));
+      builder.add(new CfSwitch(Kind.TABLE, fallthroughLabel, new int[] {min}, labels), this);
     } else {
       for (int index : targetBlockIndices()) {
         labels.add(builder.getLabel(successors.get(index)));
       }
-      builder.add(new CfSwitch(Kind.LOOKUP, fallthroughLabel, this.keys, labels));
+      builder.add(new CfSwitch(Kind.LOOKUP, fallthroughLabel, this.keys, labels), this);
     }
   }
 }
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 508b115..1296742 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
@@ -147,7 +147,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvokeDynamic(getCallSite()));
+    builder.add(new CfInvokeDynamic(getCallSite()), this);
   }
 
   @Override
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 0f2e98a..062220b 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
@@ -161,7 +161,8 @@
   @Override
   public void buildCf(CfBuilder builder) {
     builder.add(
-        new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), isInterface));
+        new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), isInterface),
+        this);
   }
 
   @Override
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 6412e17..153ca1b 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
@@ -128,7 +128,8 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvoke(org.objectweb.asm.Opcodes.INVOKEINTERFACE, getInvokedMethod(), true));
+    builder.add(
+        new CfInvoke(org.objectweb.asm.Opcodes.INVOKEINTERFACE, getInvokedMethod(), true), this);
   }
 
   @Override
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 7163fdd..63df06a 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
@@ -104,7 +104,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfMultiANewArray(type, arguments().size()));
+    builder.add(new CfMultiANewArray(type, arguments().size()), this);
   }
 
   @Override
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 425262b..ad8c087 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
@@ -104,7 +104,7 @@
     // To translate InvokePolymorphic back into InvokeVirtual, use the original prototype
     // that is stored in getProto().
     DexMethod method = factory.createMethod(dexMethod.holder, getProto(), dexMethod.name);
-    builder.add(new CfInvoke(org.objectweb.asm.Opcodes.INVOKEVIRTUAL, method, false));
+    builder.add(new CfInvoke(org.objectweb.asm.Opcodes.INVOKEVIRTUAL, method, false), this);
   }
 
   @Override
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 f1f86b3..7aa20ad 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
@@ -155,7 +155,8 @@
   @Override
   public void buildCf(CfBuilder builder) {
     builder.add(
-        new CfInvoke(org.objectweb.asm.Opcodes.INVOKESTATIC, getInvokedMethod(), isInterface));
+        new CfInvoke(org.objectweb.asm.Opcodes.INVOKESTATIC, getInvokedMethod(), isInterface),
+        this);
   }
 
   @Override
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 0a0461d..630e177 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
@@ -84,7 +84,8 @@
   @Override
   public void buildCf(CfBuilder builder) {
     builder.add(
-        new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), isInterface));
+        new CfInvoke(org.objectweb.asm.Opcodes.INVOKESPECIAL, getInvokedMethod(), isInterface),
+        this);
   }
 
   @Override
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 9179014..b5933de 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
@@ -157,7 +157,8 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfInvoke(org.objectweb.asm.Opcodes.INVOKEVIRTUAL, getInvokedMethod(), false));
+    builder.add(
+        new CfInvoke(org.objectweb.asm.Opcodes.INVOKEVIRTUAL, getInvokedMethod(), false), this);
   }
 
   @Override
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 eee3bef..fe565bc 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
@@ -76,7 +76,7 @@
   @Override
   public void buildCf(CfBuilder builder) {
     Value value = src();
-    builder.add(new CfLoad(value.outType(), builder.getLocalRegister(value)));
+    builder.add(new CfLoad(value.outType(), builder.getLocalRegister(value)), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
index 267db9b..b647ecf 100644
--- a/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
+++ b/src/main/java/com/android/tools/r8/ir/code/LogicalBinop.java
@@ -141,6 +141,6 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfLogicalBinop(getCfOpcode(), type));
+    builder.add(new CfLogicalBinop(getCfOpcode(), type), this);
   }
 }
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 f779651..648c9fd 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
@@ -137,7 +137,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfMonitor(type));
+    builder.add(new CfMonitor(type), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Neg.java b/src/main/java/com/android/tools/r8/ir/code/Neg.java
index ad0886a..459c8c5 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Neg.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Neg.java
@@ -108,6 +108,6 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfNeg(type));
+    builder.add(new CfNeg(type), this);
   }
 }
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 3be3d3d..3d6fb7d 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
@@ -152,7 +152,7 @@
   @Override
   public void buildCf(CfBuilder builder) {
     assert type.isArrayType();
-    builder.add(new CfNewArray(type));
+    builder.add(new CfNewArray(type), this);
   }
 
   @Override
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 024f6f2..3aff847 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
@@ -125,7 +125,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfNew(clazz));
+    builder.add(new CfNew(clazz), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NewUnboxedEnumInstance.java b/src/main/java/com/android/tools/r8/ir/code/NewUnboxedEnumInstance.java
index 33829cd..b56600f 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NewUnboxedEnumInstance.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NewUnboxedEnumInstance.java
@@ -132,7 +132,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfNewUnboxedEnum(clazz, ordinal));
+    builder.add(new CfNewUnboxedEnum(clazz, ordinal), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java b/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java
index e6b6f8d..5f3b592 100644
--- a/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java
+++ b/src/main/java/com/android/tools/r8/ir/code/NumberConversion.java
@@ -159,7 +159,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfNumberConversion(from, to));
+    builder.add(new CfNumberConversion(from, to), this);
   }
 
   @Override
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 a2f872e..bf8ee2d 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
@@ -79,7 +79,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(CfStackInstruction.popType(inValues.get(0).outType()));
+    builder.add(CfStackInstruction.popType(inValues.get(0).outType()), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/RecordFieldValues.java b/src/main/java/com/android/tools/r8/ir/code/RecordFieldValues.java
index 00df561..a2949d0 100644
--- a/src/main/java/com/android/tools/r8/ir/code/RecordFieldValues.java
+++ b/src/main/java/com/android/tools/r8/ir/code/RecordFieldValues.java
@@ -73,7 +73,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfRecordFieldValues(fields));
+    builder.add(new CfRecordFieldValues(fields), this);
   }
 
   @Override
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 e28ee89..1ec1a8e 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
@@ -132,7 +132,8 @@
   @Override
   public void buildCf(CfBuilder builder) {
     builder.add(
-        isReturnVoid() ? new CfReturnVoid() : new CfReturn(ValueType.fromType(getReturnType())));
+        isReturnVoid() ? new CfReturnVoid() : new CfReturn(ValueType.fromType(getReturnType())),
+        this);
   }
 
   public static class Builder extends BuilderBase<Builder, Return> {
diff --git a/src/main/java/com/android/tools/r8/ir/code/SafeCheckCast.java b/src/main/java/com/android/tools/r8/ir/code/SafeCheckCast.java
index 72a62cd..b811f86 100644
--- a/src/main/java/com/android/tools/r8/ir/code/SafeCheckCast.java
+++ b/src/main/java/com/android/tools/r8/ir/code/SafeCheckCast.java
@@ -22,7 +22,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfSafeCheckCast(getType()));
+    builder.add(new CfSafeCheckCast(getType()), this);
   }
 
   @Override
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 339f16f..2230cc7 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
@@ -221,7 +221,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfStaticFieldWrite(getField(), builder.resolveField(getField())));
+    builder.add(new CfStaticFieldWrite(getField(), builder.resolveField(getField())), this);
   }
 
   @Override
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 8100111..6714e0d 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
@@ -77,7 +77,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfStore(outType(), builder.getLocalRegister(outValue)));
+    builder.add(new CfStore(outType(), builder.getLocalRegister(outValue)), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/code/Swap.java b/src/main/java/com/android/tools/r8/ir/code/Swap.java
index 777eec1..87ed900 100644
--- a/src/main/java/com/android/tools/r8/ir/code/Swap.java
+++ b/src/main/java/com/android/tools/r8/ir/code/Swap.java
@@ -67,7 +67,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfStackInstruction(Opcode.Swap));
+    builder.add(new CfStackInstruction(Opcode.Swap), this);
   }
 
   @Override
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 6f47788..6350255 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
@@ -83,7 +83,7 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfThrow());
+    builder.add(new CfThrow(), this);
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
index da6c3bf..4f4a7b2 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/CfBuilder.java
@@ -695,7 +695,7 @@
     return registerAllocator.getRegisterForValue(value);
   }
 
-  public void add(CfInstruction instruction) {
+  private void add(CfInstruction instruction) {
     instructions.add(instruction);
   }
 
@@ -704,7 +704,16 @@
     add(instruction);
   }
 
+  public void add(CfInstruction... instructions) {
+    Collections.addAll(this.instructions, instructions);
+  }
+
   public void addArgument(Argument argument) {
     // Nothing so far.
   }
+
+  public boolean verifyNoMetadata(Instruction instruction) {
+    assert bytecodeMetadataBuilder.verifyNoMetadata(instruction);
+    return true;
+  }
 }
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 07fb168..efd8593 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
@@ -1486,7 +1486,13 @@
 
     printMethod(code, "Optimized IR (SSA)", previous);
     timing.begin("Finalize IR");
-    finalizeIR(code, feedback, conversionOptions, bytecodeMetadataProviderBuilder.build(), timing);
+    finalizeIR(
+        context,
+        code,
+        feedback,
+        conversionOptions,
+        bytecodeMetadataProviderBuilder.build(),
+        timing);
     timing.end();
     return timing;
   }
@@ -1579,6 +1585,7 @@
     }
     deadCodeRemover.run(code, timing);
     finalizeIR(
+        code.context(),
         code,
         feedback,
         DefaultMethodConversionOptions.getInstance(),
@@ -1587,6 +1594,7 @@
   }
 
   public void finalizeIR(
+      ProgramMethod method,
       IRCode code,
       OptimizationFeedback feedback,
       MethodConversionOptions conversionOptions,