Check soundness of IR metadata

Change-Id: Idf910b1dbd5da3ecb28a9d8b345428c60e1b20c2
diff --git a/src/main/java/com/android/tools/r8/ir/code/IRCode.java b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
index 98bb2e7..e6b352e 100644
--- a/src/main/java/com/android/tools/r8/ir/code/IRCode.java
+++ b/src/main/java/com/android/tools/r8/ir/code/IRCode.java
@@ -533,6 +533,7 @@
     assert consistentPredecessorSuccessors();
     assert consistentCatchHandlers();
     assert consistentBlockInstructions();
+    assert consistentMetadata();
     assert !allThrowingInstructionsHavePositions || computeAllThrowingInstructionsHavePositions();
     return true;
   }
@@ -715,6 +716,21 @@
     return true;
   }
 
+  private boolean consistentMetadata() {
+    for (Instruction instruction : instructions()) {
+      if (instruction.isConstString()) {
+        assert mayHaveConstString : "IR metadata should indicate that code has a const-string";
+      } else if (instruction.isDebugPosition()) {
+        assert mayHaveDebugPositions : "IR metadata should indicate that code has a debug position";
+      } else if (instruction.isMonitor()) {
+        assert mayHaveMonitorInstruction : "IR metadata should indicate that code has a monitor";
+      } else if (instruction.isStringSwitch()) {
+        assert mayHaveStringSwitch : "IR metadata should indicate that code has a string-switch";
+      }
+    }
+    return true;
+  }
+
   private boolean validThrowingInstructions() {
     for (BasicBlock block : blocks) {
       if (block.hasCatchHandlers()) {
diff --git a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
index 0036cd3..ef6f3eb 100644
--- a/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
+++ b/src/main/java/com/android/tools/r8/ir/conversion/IRBuilder.java
@@ -652,11 +652,11 @@
           current = position;
           hasDebugPositions = hasDebugPositions || position.isSome();
         } else if (instruction.isDebugPosition()) {
-          hasDebugPositions = true;
           if (position.equals(current)) {
             it.removeOrReplaceByDebugLocalRead();
           } else {
             current = position;
+            hasDebugPositions = true;
           }
         } else if (position.isSome() && !position.synthetic && !position.equals(current)) {
           DebugPosition positionChange = new DebugPosition();
@@ -665,6 +665,7 @@
           it.add(positionChange);
           it.next();
           current = position;
+          hasDebugPositions = true;
         }
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
index d1852bb..f68f740 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/StringConcatRewriter.java
@@ -447,6 +447,7 @@
                 value,
                 factory.createString(str),
                 ThrowingInfo.defaultForConstString(appView.options())));
+        code.mayHaveConstString = true;
         return value;
       }
     }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
index bcc6d4e..862c82d 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/CodeRewriter.java
@@ -3699,6 +3699,7 @@
       } else if (isNameInvoke) {
         iterator.replaceCurrentInstruction(
             new ConstString(outValue, enumField.name, ThrowingInfo.NO_THROW));
+        code.mayHaveConstString = true;
       } else {
         assert isToStringInvoke;
         DexClass enumClazz = appView.appInfo().definitionFor(enumField.type);
@@ -3712,6 +3713,7 @@
         }
         iterator.replaceCurrentInstruction(
             new ConstString(outValue, enumField.name, ThrowingInfo.NO_THROW));
+        code.mayHaveConstString = true;
       }
     }
 
@@ -4101,6 +4103,7 @@
     }
     // When we fall out of the loop the iterator is in the last eol block.
     iterator.add(new InvokeVirtual(printLn, null, ImmutableList.of(out, empty)));
+    code.mayHaveConstString = true;
   }
 
   public static void ensureDirectStringNewToInit(IRCode code, DexItemFactory dexItemFactory) {
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
index c8bd65d..f8b0eae 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/MemberValuePropagation.java
@@ -238,6 +238,7 @@
         iterator.add(replacement);
       }
     }
+    code.mayHaveConstString |= replacement.isConstString();
     return true;
   }
 
@@ -307,6 +308,7 @@
         replacement =
             createConstStringReplacement(
                 code, constant, current.outValue().getTypeLattice(), current.getLocalInfo());
+        code.mayHaveConstString = true;
       }
 
       affectedValues.addAll(current.outValue().affectedValues());
@@ -368,6 +370,7 @@
       if (replacement != null) {
         affectedValues.addAll(current.outValue().affectedValues());
         iterator.replaceCurrentInstruction(replacement);
+        code.mayHaveConstString |= replacement.isConstString();
         if (replacement.isDexItemBasedConstString()) {
           code.method.getMutableOptimizationInfo().markUseIdentifierNameString();
         }
@@ -431,6 +434,7 @@
     if (replacement != null) {
       affectedValues.add(replacement.outValue());
       iterator.replaceCurrentInstruction(replacement);
+      code.mayHaveConstString |= replacement.isConstString();
       if (replacement.isDexItemBasedConstString()) {
         code.method.getMutableOptimizationInfo().markUseIdentifierNameString();
       }
diff --git a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
index eac9284..6a6a05e 100644
--- a/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
+++ b/src/main/java/com/android/tools/r8/ir/optimize/string/StringOptimizer.java
@@ -339,6 +339,7 @@
                 invoke.getLocalInfo());
         ConstString constString = new ConstString(stringValue, name, throwingInfo);
         it.replaceCurrentInstruction(constString);
+        code.mayHaveConstString = true;
       } else if (deferred != null) {
         it.replaceCurrentInstruction(deferred);
         markUseIdentifierNameString = true;
@@ -376,6 +377,7 @@
           ConstString nullString =
               new ConstString(nullStringValue, factory.createString("null"), throwingInfo);
           it.replaceCurrentInstruction(nullString);
+          code.mayHaveConstString = true;
         } else if (inType.nullability().isDefinitelyNotNull()
             && inType.isClassType()
             && inType.asClassTypeLatticeElement().getClassType().equals(factory.stringType)) {