Merge "Fix register allocation of arguments and triage remaining example tests."
diff --git a/src/main/java/com/android/tools/r8/cf/CfPrinter.java b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
index af51fdc..3fd7d75 100644
--- a/src/main/java/com/android/tools/r8/cf/CfPrinter.java
+++ b/src/main/java/com/android/tools/r8/cf/CfPrinter.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.cf.code.CfFrame;
 import com.android.tools.r8.cf.code.CfGoto;
 import com.android.tools.r8.cf.code.CfIf;
+import com.android.tools.r8.cf.code.CfIfCmp;
 import com.android.tools.r8.cf.code.CfInstruction;
 import com.android.tools.r8.cf.code.CfInvoke;
 import com.android.tools.r8.cf.code.CfLabel;
@@ -17,6 +18,7 @@
 import com.android.tools.r8.cf.code.CfNew;
 import com.android.tools.r8.cf.code.CfPop;
 import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfReturnVoid;
 import com.android.tools.r8.cf.code.CfStaticGet;
 import com.android.tools.r8.cf.code.CfStore;
 import com.android.tools.r8.errors.Unreachable;
@@ -24,6 +26,8 @@
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
+import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.If.Type;
 import com.android.tools.r8.ir.code.ValueType;
 import java.util.HashMap;
 import java.util.Map;
@@ -101,10 +105,14 @@
     }
   }
 
-  public void print(CfReturn ret) {
+  public void print(CfReturnVoid ret) {
     print("return");
   }
 
+  public void print(CfReturn ret) {
+    print(typePrefix(ret.getType()) + "return");
+  }
+
   public void print(CfPop pop) {
     print("pop");
   }
@@ -198,39 +206,29 @@
     builder.append("goto ").append(getLabel(jump.getTarget()));
   }
 
+  private String ifPostfix(If.Type kind) {
+    return kind.toString().toLowerCase();
+  }
+
   public void print(CfIf conditional) {
     indent();
-    switch (conditional.getOpcode()) {
-      case Opcodes.IFNULL:
-        builder.append("ifnull");
-        break;
-      case Opcodes.IFNONNULL:
-        builder.append("ifnonnull");
-        break;
-      case Opcodes.IFEQ:
-        builder.append("ifeq");
-        break;
-      case Opcodes.IFNE:
-        builder.append("ifne");
-        break;
-      case Opcodes.IFLT:
-        builder.append("iflt");
-        break;
-      case Opcodes.IFGE:
-        builder.append("ifge");
-        break;
-      case Opcodes.IFGT:
-        builder.append("ifgt");
-        break;
-      case Opcodes.IFLE:
-        builder.append("ifle");
-        break;
-      default:
-        throw new Unreachable();
+    if (conditional.getType().isObject()) {
+      builder.append("if").append(conditional.getKind() == Type.EQ ? "null" : "nonnull");
+    } else {
+      builder.append("if").append(ifPostfix(conditional.getKind()));
     }
     builder.append(' ').append(getLabel(conditional.getTarget()));
   }
 
+  public void print(CfIfCmp conditional) {
+    indent();
+    builder
+        .append(conditional.getType().isObject() ? "if_acmp" : "if_icmp")
+        .append(ifPostfix(conditional.getKind()))
+        .append(' ')
+        .append(getLabel(conditional.getTarget()));
+  }
+
   public void print(CfLoad load) {
     print(load.getType(), "load", load.getLocalIndex());
   }
diff --git a/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java b/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
index 1c7c6d9..1a60a02 100644
--- a/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/cf/CfRegisterAllocator.java
@@ -128,6 +128,12 @@
 
   private void performLinearScan() {
     unhandled.addAll(liveIntervals);
+
+    while (!unhandled.isEmpty() && unhandled.peek().getValue().isArgument()) {
+      LiveIntervals argument = unhandled.poll();
+      assignRegisterToUnhandledInterval(argument, getNextFreeRegister(argument.getType().isWide()));
+    }
+
     while (!unhandled.isEmpty()) {
       LiveIntervals unhandledInterval = unhandled.poll();
       int start = unhandledInterval.getStart();
diff --git a/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java b/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
index bb76dc7..ae8e6b1 100644
--- a/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/LoadStoreHelper.java
@@ -86,11 +86,12 @@
   public void loadInValues(Instruction instruction, InstructionListIterator it) {
     int topOfStack = 0;
     it.previous();
-    for (Value value : instruction.inValues()) {
+    for (int i = 0; i < instruction.inValues().size(); i++) {
+      Value value = instruction.inValues().get(i);
       StackValue stackValue = createStackValue(value, topOfStack++);
       add(load(stackValue, value), instruction, it);
       value.removeUser(instruction);
-      instruction.replaceValue(value, stackValue);
+      instruction.replaceValue(i, stackValue);
     }
     it.next();
   }
diff --git a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
index d22ff65..77ecbdc 100644
--- a/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
+++ b/src/main/java/com/android/tools/r8/cf/TypeVerificationHelper.java
@@ -67,8 +67,10 @@
                 ? code.method.method.getHolder()
                 : code.method.method.proto.parameters.values[argumentIndex];
         Value outValue = instruction.outValue();
-        types.put(outValue, argumentType);
-        addUsers(outValue, worklist);
+        if (outValue.outType().isObject()) {
+          types.put(outValue, argumentType);
+          addUsers(outValue, worklist);
+        }
         ++argumentIndex;
       }
       // Compute the out-value type of each normal instruction with an out-value but no in values.
@@ -90,6 +92,7 @@
     while (!worklist.isEmpty()) {
       Value item = worklist.iterator().next();
       worklist.remove(item);
+      assert item.outType().isObject();
       DexType previousType = types.get(item);
       DexType refinedType = computeVerificationType(item);
       if (previousType != refinedType) {
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
index 1d946b2..b4c6755 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfFrame.java
@@ -9,7 +9,6 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexType;
-import it.unimi.dsi.fastutil.ints.Int2ReferenceMap.Entry;
 import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
@@ -22,24 +21,45 @@
     this.locals = locals;
   }
 
+  private boolean isWide(DexType type) {
+    return type.isPrimitiveType() && (type.toShorty() == 'J' || type.toShorty() == 'D');
+  }
+
   @Override
   public void write(MethodVisitor visitor) {
-    int type = F_NEW;
-    int localsSize = locals.size();
-    Object[] localsCopy = new Object[localsSize];
-    int localIndex = 0;
-    for (Entry<DexType> entry : locals.int2ReferenceEntrySet()) {
-      Object typeOpcode = getType(entry.getValue());
-      if (typeOpcode == Opcodes.LONG || typeOpcode == Opcodes.DOUBLE) {
-        localsCopy[localIndex++] = Opcodes.TOP;
+    if (locals.isEmpty()) {
+      visitor.visitFrame(F_NEW, 0, null, 0, null);
+      return;
+    }
+    // Compute the size of locals. Absent indexes are denoted by a single-width element (ie, TOP).
+    int maxRegister = locals.lastIntKey();
+    int localsCount = 0;
+    for (int i = 0; i <= maxRegister; i++) {
+      localsCount++;
+      DexType type = locals.get(i);
+      if (type != null && isWide(type)) {
+        i++;
       }
+    }
+    // Construct the locals type descriptions.
+    Object[] localsCopy = new Object[localsCount];
+    int localIndex = 0;
+    for (int i = 0; i <= maxRegister; i++) {
+      DexType type = locals.get(i);
+      Object typeOpcode = getType(type);
       localsCopy[localIndex++] = typeOpcode;
+      if (type != null && isWide(type)) {
+        i++;
+      }
     }
     // TODO(zerny): Compute the stack types too.
-    visitor.visitFrame(type, localsSize, localsCopy, 0, new Object[0]);
+    visitor.visitFrame(F_NEW, localsCount, localsCopy, 0, null);
   }
 
   private Object getType(DexType type) {
+    if (type == null) {
+      return Opcodes.TOP;
+    }
     if (type == DexItemFactory.nullValueType) {
       return Opcodes.NULL;
     }
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIf.java b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
index 5c7a2c7..d928ff7 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfIf.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIf.java
@@ -6,6 +6,7 @@
 import com.android.tools.r8.cf.CfPrinter;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.If.Type;
 import com.android.tools.r8.ir.code.ValueType;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
@@ -22,6 +23,14 @@
     this.target = target;
   }
 
+  public ValueType getType() {
+    return type;
+  }
+
+  public Type getKind() {
+    return kind;
+  }
+
   public CfLabel getTarget() {
     return target;
   }
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
new file mode 100644
index 0000000..dc8b63f
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/cf/code/CfIfCmp.java
@@ -0,0 +1,66 @@
+// Copyright (c) 2017, 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.cf.code;
+
+import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.code.If;
+import com.android.tools.r8.ir.code.If.Type;
+import com.android.tools.r8.ir.code.ValueType;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class CfIfCmp extends CfInstruction {
+
+  private final If.Type kind;
+  private final ValueType type;
+  private final CfLabel target;
+
+  public CfIfCmp(If.Type kind, ValueType type, CfLabel target) {
+    this.kind = kind;
+    this.type = type;
+    this.target = target;
+  }
+
+  public Type getKind() {
+    return kind;
+  }
+
+  public ValueType getType() {
+    return type;
+  }
+
+  public CfLabel getTarget() {
+    return target;
+  }
+
+  public int getOpcode() {
+    switch (kind) {
+      case EQ:
+        return type.isObject() ? Opcodes.IF_ACMPEQ : Opcodes.IF_ICMPEQ;
+      case GE:
+        return Opcodes.IF_ICMPGE;
+      case GT:
+        return Opcodes.IF_ICMPGT;
+      case LE:
+        return Opcodes.IF_ICMPLE;
+      case LT:
+        return Opcodes.IF_ICMPLT;
+      case NE:
+        return type.isObject() ? Opcodes.IF_ACMPNE : Opcodes.IF_ICMPNE;
+      default:
+        throw new Unreachable("Unexpected type " + type);
+    }
+  }
+
+  @Override
+  public void print(CfPrinter printer) {
+    printer.print(this);
+  }
+
+  @Override
+  public void write(MethodVisitor visitor) {
+    visitor.visitJumpInsn(getOpcode(), target.getLabel());
+  }
+}
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
index 1a20d29..c426dbd 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturn.java
@@ -4,14 +4,43 @@
 package com.android.tools.r8.cf.code;
 
 import com.android.tools.r8.cf.CfPrinter;
+import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.ir.code.ValueType;
 import org.objectweb.asm.MethodVisitor;
 import org.objectweb.asm.Opcodes;
 
 public class CfReturn extends CfInstruction {
 
+  private final ValueType type;
+
+  public CfReturn(ValueType type) {
+    this.type = type;
+  }
+
+  public ValueType getType() {
+    return type;
+  }
+
+  private int getOpcode() {
+    switch (type) {
+      case INT:
+        return Opcodes.IRETURN;
+      case FLOAT:
+        return Opcodes.FRETURN;
+      case LONG:
+        return Opcodes.LRETURN;
+      case DOUBLE:
+        return Opcodes.DRETURN;
+      case OBJECT:
+        return Opcodes.ARETURN;
+      default:
+        throw new Unreachable("Unexpected return type: " + type);
+    }
+  }
+
   @Override
   public void write(MethodVisitor visitor) {
-    visitor.visitInsn(Opcodes.RETURN);
+    visitor.visitInsn(getOpcode());
   }
 
   @Override
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
new file mode 100644
index 0000000..b8bfc7d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/cf/code/CfReturnVoid.java
@@ -0,0 +1,21 @@
+// Copyright (c) 2017, 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.cf.code;
+
+import com.android.tools.r8.cf.CfPrinter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+public class CfReturnVoid extends CfInstruction {
+
+  @Override
+  public void write(MethodVisitor visitor) {
+    visitor.visitInsn(Opcodes.RETURN);
+  }
+
+  @Override
+  public void print(CfPrinter printer) {
+    printer.print(this);
+  }
+}
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 c6e62af..37a6766 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
@@ -8,6 +8,7 @@
 
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.cf.code.CfIf;
+import com.android.tools.r8.cf.code.CfIfCmp;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
@@ -197,7 +198,12 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    assert inValues.size() == 1;
-    builder.add(new CfIf(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
+    if (inValues.size() == 1) {
+      builder.add(new CfIf(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
+      return;
+    }
+    assert inValues.size() == 2;
+    assert inValues.get(0).type == inValues.get(1).type;
+    builder.add(new CfIfCmp(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
   }
 }
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 ca68f64..dce6226 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
@@ -149,6 +149,11 @@
     }
   }
 
+  public void replaceValue(int index, Value newValue) {
+    inValues.set(index, newValue);
+    newValue.addUser(this);
+  }
+
   public void replaceDebugValue(Value oldValue, Value newValue) {
     if (debugValues.remove(oldValue)) {
       if (newValue.hasLocalInfo()) {
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 1177abb..a9c44c6 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
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.cf.LoadStoreHelper;
 import com.android.tools.r8.cf.code.CfReturn;
+import com.android.tools.r8.cf.code.CfReturnVoid;
 import com.android.tools.r8.code.MoveType;
 import com.android.tools.r8.code.ReturnObject;
 import com.android.tools.r8.code.ReturnVoid;
@@ -125,6 +126,6 @@
 
   @Override
   public void buildCf(CfBuilder builder) {
-    builder.add(new CfReturn());
+    builder.add(isReturnVoid() ? new CfReturnVoid() : new CfReturn(returnType));
   }
 }
diff --git a/src/main/java/com/android/tools/r8/ir/code/StackValue.java b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
index 94909db..46aa5db 100644
--- a/src/main/java/com/android/tools/r8/ir/code/StackValue.java
+++ b/src/main/java/com/android/tools/r8/ir/code/StackValue.java
@@ -19,7 +19,7 @@
   }
 
   public static StackValue forObjectType(DexType type, int height) {
-    assert DexItemFactory.nullValueType == type || type.isClassType();
+    assert DexItemFactory.nullValueType == type || type.isClassType() || type.isArrayType();
     return new StackValue(type, ValueType.OBJECT, height);
   }
 
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 f1c3e32..f923493 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
@@ -244,6 +244,7 @@
     assert stack.isEmpty();
     Collection<Value> locals = registerAllocator.getLocalsAtPosition(block.entry().getNumber());
     Int2ReferenceSortedMap<DexType> mapping = new Int2ReferenceAVLTreeMap<>();
+
     for (Value local : locals) {
       DexType type;
       switch (local.outType()) {
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 8207e4c..b466315 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
@@ -611,7 +611,7 @@
   }
 
   private void finalizeToCf(DexEncodedMethod method, IRCode code, OptimizationFeedback feedback) {
-    assert method.getCode().isJarCode();
+    assert !method.getCode().isDexCode();
     CfBuilder builder = new CfBuilder(method, code, options.itemFactory);
     // TODO(zerny): Change the return type of CfBuilder::build CfCode once complete.
     Code result = builder.build(codeRewriter, options);
diff --git a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
index d2b2f5e..0d2cf2a 100644
--- a/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/jar/CfApplicationWriter.java
@@ -62,7 +62,7 @@
 
   private void writeClass(DexProgramClass clazz, OutputSink outputSink) throws IOException {
     ClassWriter writer = new ClassWriter(0);
-    writer.visitSource(clazz.sourceFile.toString(), null);
+    writer.visitSource(clazz.sourceFile != null ? clazz.sourceFile.toString() : null, null);
     int version = downgrade(clazz.getClassFileVersion());
     int access = clazz.accessFlags.getAsCfAccessFlags();
     String desc = clazz.type.toDescriptorString();
@@ -75,10 +75,13 @@
       interfaces[i] = clazz.interfaces.values[i].getInternalName();
     }
     writer.visit(version, access, name, signature, superName, interfaces);
-    // TODO(zerny): Methods and fields.
+    // TODO(zerny): Fields.
     for (DexEncodedMethod method : clazz.directMethods()) {
       writeMethod(method, writer);
     }
+    for (DexEncodedMethod method : clazz.virtualMethods()) {
+      writeMethod(method, writer);
+    }
     writer.visitEnd();
 
     byte[] result = writer.toByteArray();
@@ -93,7 +96,9 @@
     String signature = null; // TODO(zerny): Support generic signatures.
     String[] exceptions = null;
     MethodVisitor visitor = writer.visitMethod(access, name, desc, signature, exceptions);
-    writeCode(method.getCode(), visitor);
+    if (!method.accessFlags.isAbstract()) {
+      writeCode(method.getCode(), visitor);
+    }
   }
 
   private void writeCode(Code code, MethodVisitor visitor) {
diff --git a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
index c79719a..6eb5090 100644
--- a/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
+++ b/src/test/java/com/android/tools/r8/R8RunExamplesTest.java
@@ -18,6 +18,7 @@
 import com.android.tools.r8.shaking.ProguardRuleParserException;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -62,6 +63,30 @@
           .put("memberrebinding2.Test", match(R8_COMPILER)) // b/38187737
           .build();
 
+  private static final Map<String, TestCondition> failingRunCf =
+      new ImmutableMap.Builder<String, TestCondition>()
+          .put("floating_point_annotations.FloatingPointValuedAnnotationTest", match(R8_COMPILER))
+          .put("filledarray.FilledArray", match(R8_COMPILER)) // missing field
+          .put("instancevariable.InstanceVariable", match(R8_COMPILER)) // missing field
+          .put("newarray.NewArray", match(R8_COMPILER)) // missing field
+          .put("regalloc.RegAlloc", match(R8_COMPILER)) // missing field
+          .put("staticfield.StaticField", match(R8_COMPILER)) // missing field
+          .put("sync.Sync", match(R8_COMPILER)) // missing field
+          .put("throwing.Throwing", match(R8_COMPILER)) // missing field
+          .put("regress_64881691.Regress", match(R8_COMPILER)) // missing field
+          .put("memberrebinding2.Memberrebinding", match(R8_COMPILER)) // missing field
+          .put("interfaceinlining.Main", match(R8_COMPILER)) // missing field
+          .put("switchmaps.Switches", match(R8_COMPILER)) // missing field
+          .put("regress_62300145.Regress", match(R8_COMPILER)) // verify <init> failed
+          .put("enclosingmethod.Main", match(R8_COMPILER)) // verify <init> failed
+          .build();
+
+  private static final Set<String> failingCompileCf =
+      new ImmutableSet.Builder<String>()
+          .add("invoke.Invoke") // outline / CF->IR
+          .add("trycatch.TryCatch") // inline / CF->IR
+          .build();
+
   private static final Map<String, TestCondition> outputNotIdenticalToJVMOutput =
       new ImmutableMap.Builder<String, TestCondition>()
           // Traverses stack frames that contain Art specific frames.
@@ -123,16 +148,9 @@
         "switchmaps.Switches",
     };
 
-    String[] javaBytecodeTests = {
-        "constants.Constants",
-        "hello.Hello",
-        "arithmetic.Arithmetic",
-        "barray.BArray",
-    };
-
     List<String[]> fullTestList = new ArrayList<>(tests.length * 2);
-    if (!ONLY_RUN_CF_TESTS) {
-      for (String test : tests) {
+    for (String test : tests) {
+      if (!ONLY_RUN_CF_TESTS) {
         fullTestList.add(makeTest(Input.JAVAC, CompilerUnderTest.D8, CompilationMode.DEBUG, test));
         fullTestList.add(makeTest(Input.JAVAC_ALL, CompilerUnderTest.D8, CompilationMode.DEBUG,
             test));
@@ -146,16 +164,10 @@
             test));
         fullTestList.add(makeTest(Input.DX, CompilerUnderTest.R8, CompilationMode.RELEASE, test));
       }
-    }
-    // TODO(zerny): Once all tests pass create the java tests in the main test loop.
-    for (String test : javaBytecodeTests) {
-      fullTestList.add(
-          makeTest(Input.JAVAC_ALL, CompilerUnderTest.R8, CompilationMode.DEBUG, test, Output.CF));
       fullTestList.add(
           makeTest(
               Input.JAVAC_ALL, CompilerUnderTest.R8, CompilationMode.RELEASE, test, Output.CF));
     }
-
     return fullTestList;
   }
 
@@ -236,6 +248,9 @@
   @Before
   public void compile()
       throws IOException, ProguardRuleParserException, ExecutionException, CompilationException {
+    if (output == Output.CF && failingCompileCf.contains(mainClass)) {
+      thrown.expect(Throwable.class);
+    }
     switch (compiler) {
       case D8: {
         assertTrue(output == Output.DEX);
@@ -277,6 +292,15 @@
       fail("JVM failed for: " + mainClass);
     }
 
+    DexVm vm = ToolHelper.getDexVm();
+    TestCondition condition =
+        output == Output.CF ? failingRunCf.get(mainClass) : failingRun.get(mainClass);
+    if (condition != null && condition.test(getTool(), compiler, vm.getVersion(), mode)) {
+      thrown.expect(Throwable.class);
+    } else {
+      thrown = ExpectedException.none();
+    }
+
     if (output == Output.CF) {
       ToolHelper.ProcessResult result =
           ToolHelper.runJava(ImmutableList.of(generated.toString()), mainClass);
@@ -291,14 +315,6 @@
       return;
     }
 
-    DexVm vm = ToolHelper.getDexVm();
-    TestCondition condition = failingRun.get(mainClass);
-    if (condition != null && condition.test(getTool(), compiler, vm.getVersion(), mode)) {
-      thrown.expect(Throwable.class);
-    } else {
-      thrown = ExpectedException.none();
-    }
-
     // Check output against Art output on original dex file.
     String output =
         ToolHelper.checkArtOutputIdentical(original, generated.toString(), mainClass, vm);