[LIR] Add new-instance, invoke and cmp instructions.

Bug: b/225838009
Change-Id: I00cbfa596e09f653ac3d552f360d6cb5e817711b
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 a03637e..bc4cf73 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
@@ -19,6 +19,7 @@
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.conversion.CfBuilder;
 import com.android.tools.r8.ir.conversion.DexBuilder;
+import com.android.tools.r8.lightir.LirBuilder;
 import com.android.tools.r8.utils.LongInterval;
 import com.android.tools.r8.utils.StringUtils;
 import com.android.tools.r8.utils.StringUtils.BraceType;
@@ -236,6 +237,11 @@
   }
 
   @Override
+  public void buildLir(LirBuilder<Value, ?> builder) {
+    builder.addCmp(type, bias, leftValue(), rightValue());
+  }
+
+  @Override
   public TypeElement evaluate(AppView<?> appView) {
     return TypeElement.getInt();
   }
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 94ba6c4..2936292 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
@@ -26,6 +26,7 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.lightir.LirBuilder;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.List;
 
@@ -165,4 +166,9 @@
   void internalRegisterUse(UseRegistry<?> registry, DexClassAndMethod context) {
     registry.registerInvokeInterface(getInvokedMethod());
   }
+
+  @Override
+  public void buildLir(LirBuilder<Value, ?> builder) {
+    builder.addInvokeInterface(getInvokedMethod(), arguments());
+  }
 }
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 c84568c..3acd5fc 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
@@ -29,6 +29,7 @@
 import com.android.tools.r8.ir.optimize.Inliner.Reason;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
 import com.android.tools.r8.ir.optimize.inliner.WhyAreYouNotInliningReporter;
+import com.android.tools.r8.lightir.LirBuilder;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import java.util.List;
 
@@ -244,6 +245,11 @@
     registry.registerInvokeStatic(getInvokedMethod());
   }
 
+  @Override
+  public void buildLir(LirBuilder<Value, ?> builder) {
+    builder.addInvokeStatic(getInvokedMethod(), arguments());
+  }
+
   public static class Builder extends InvokeMethod.Builder<Builder, InvokeStatic> {
 
     @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 40e7d5d..0fa2583 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
@@ -29,6 +29,7 @@
 import com.android.tools.r8.ir.conversion.DexBuilder;
 import com.android.tools.r8.ir.optimize.Inliner.ConstraintWithTarget;
 import com.android.tools.r8.ir.optimize.InliningConstraints;
+import com.android.tools.r8.lightir.LirBuilder;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 
 public class NewInstance extends Instruction {
@@ -239,6 +240,11 @@
     registry.registerNewInstance(clazz);
   }
 
+  @Override
+  public void buildLir(LirBuilder<Value, ?> builder) {
+    builder.addNewInstance(clazz);
+  }
+
   public static class Builder extends BuilderBase<Builder, NewInstance> {
 
     private DexType type;
diff --git a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
index e09e9f5..95591f5 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -3,17 +3,21 @@
 // BSD-style license that can be found in the LICENSE file.
 package com.android.tools.r8.lightir;
 
+import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexField;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.graph.DexType;
 import com.android.tools.r8.graph.ProgramMethod;
+import com.android.tools.r8.ir.analysis.type.Nullability;
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.Argument;
 import com.android.tools.r8.ir.code.ArrayLength;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.Cmp;
+import com.android.tools.r8.ir.code.Cmp.Bias;
 import com.android.tools.r8.ir.code.ConstNumber;
 import com.android.tools.r8.ir.code.ConstString;
 import com.android.tools.r8.ir.code.DebugLocalWrite;
@@ -25,8 +29,11 @@
 import com.android.tools.r8.ir.code.IfType;
 import com.android.tools.r8.ir.code.Instruction;
 import com.android.tools.r8.ir.code.InvokeDirect;
+import com.android.tools.r8.ir.code.InvokeInterface;
+import com.android.tools.r8.ir.code.InvokeStatic;
 import com.android.tools.r8.ir.code.InvokeVirtual;
 import com.android.tools.r8.ir.code.MoveException;
+import com.android.tools.r8.ir.code.NewInstance;
 import com.android.tools.r8.ir.code.NumberGenerator;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.ir.code.Phi;
@@ -91,8 +98,6 @@
         AppView<?> appView,
         LirDecodingStrategy<Value, EV> strategy) {
       super(code);
-      assert code.getPositionTable().length > 0;
-      assert code.getPositionTable()[0].fromInstructionIndex == 0;
       this.appView = appView;
       this.code = code;
       this.strategy = strategy;
@@ -370,6 +375,23 @@
       addInstruction(instruction);
     }
 
+    @Override
+    public void onInvokeStatic(DexMethod target, List<EV> arguments) {
+      // TODO(b/225838009): Maintain is-interface bit.
+      Value dest = getInvokeInstructionOutputValue(target);
+      List<Value> ssaArgumentValues = getValues(arguments);
+      InvokeStatic instruction = new InvokeStatic(target, dest, ssaArgumentValues);
+      addInstruction(instruction);
+    }
+
+    @Override
+    public void onInvokeInterface(DexMethod target, List<EV> arguments) {
+      Value dest = getInvokeInstructionOutputValue(target);
+      List<Value> ssaArgumentValues = getValues(arguments);
+      InvokeInterface instruction = new InvokeInterface(target, dest, ssaArgumentValues);
+      addInstruction(instruction);
+    }
+
     private Value getInvokeInstructionOutputValue(DexMethod target) {
       return target.getReturnType().isVoidType()
           ? null
@@ -377,6 +399,13 @@
     }
 
     @Override
+    public void onNewInstance(DexType clazz) {
+      TypeElement type = TypeElement.fromDexType(clazz, Nullability.definitelyNotNull(), appView);
+      Value dest = getOutValueForNextInstruction(type);
+      addInstruction(new NewInstance(clazz, dest));
+    }
+
+    @Override
     public void onStaticGet(DexField field) {
       Value dest = getOutValueForNextInstruction(field.getTypeElement(appView));
       addInstruction(new StaticGet(dest, field));
@@ -425,5 +454,39 @@
       dest.setType(type);
       addInstruction(new DebugLocalWrite(dest, src));
     }
+
+    @Override
+    public void onCmpInstruction(int opcode, EV leftIndex, EV rightIndex) {
+      NumericType type;
+      Bias bias;
+      switch (opcode) {
+        case LirOpcodes.LCMP:
+          type = NumericType.LONG;
+          bias = Bias.NONE;
+          break;
+        case LirOpcodes.FCMPL:
+          type = NumericType.FLOAT;
+          bias = Bias.LT;
+          break;
+        case LirOpcodes.FCMPG:
+          type = NumericType.FLOAT;
+          bias = Bias.GT;
+          break;
+        case LirOpcodes.DCMPL:
+          type = NumericType.DOUBLE;
+          bias = Bias.LT;
+          break;
+        case LirOpcodes.DCMPG:
+          type = NumericType.DOUBLE;
+          bias = Bias.GT;
+          break;
+        default:
+          throw new Unreachable("Unexpected cmp opcode: " + opcode);
+      }
+      Value leftValue = getValue(leftIndex);
+      Value rightValue = getValue(rightIndex);
+      Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+      addInstruction(new Cmp(type, bias, dest, leftValue, rightValue));
+    }
   }
 }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
index fd4113a..7730e8f 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -15,6 +15,8 @@
 import com.android.tools.r8.ir.analysis.type.TypeElement;
 import com.android.tools.r8.ir.code.BasicBlock;
 import com.android.tools.r8.ir.code.CatchHandlers;
+import com.android.tools.r8.ir.code.Cmp;
+import com.android.tools.r8.ir.code.Cmp.Bias;
 import com.android.tools.r8.ir.code.IRMetadata;
 import com.android.tools.r8.ir.code.IfType;
 import com.android.tools.r8.ir.code.NumericType;
@@ -208,6 +210,11 @@
         opcode, Collections.emptyList(), Collections.singletonList(value));
   }
 
+  private LirBuilder<V, EV> addTwoValueInstruction(int opcode, V leftValue, V rightValue) {
+    return addInstructionTemplate(
+        opcode, Collections.emptyList(), ImmutableList.of(leftValue, rightValue));
+  }
+
   private LirBuilder<V, EV> addInstructionTemplate(
       int opcode, List<DexItem> items, List<V> values) {
     assert values.size() < MAX_VALUE_COUNT;
@@ -303,6 +310,18 @@
     return addInvokeInstruction(LirOpcodes.INVOKEVIRTUAL, method, arguments);
   }
 
+  public LirBuilder<V, EV> addInvokeStatic(DexMethod method, List<V> arguments) {
+    return addInvokeInstruction(LirOpcodes.INVOKESTATIC, method, arguments);
+  }
+
+  public LirBuilder<V, EV> addInvokeInterface(DexMethod method, List<V> arguments) {
+    return addInvokeInstruction(LirOpcodes.INVOKEINTERFACE, method, arguments);
+  }
+
+  public LirBuilder<V, EV> addNewInstance(DexType clazz) {
+    return addOneItemInstruction(LirOpcodes.NEW, clazz);
+  }
+
   public LirBuilder<V, EV> addReturn(V value) {
     throw new Unimplemented();
   }
@@ -435,4 +454,21 @@
         debugTable,
         strategy.getStrategyInfo());
   }
+
+  private int getCmpOpcode(NumericType type, Cmp.Bias bias) {
+    switch (type) {
+      case LONG:
+        return LirOpcodes.LCMP;
+      case FLOAT:
+        return bias == Cmp.Bias.LT ? LirOpcodes.FCMPL : LirOpcodes.FCMPG;
+      case DOUBLE:
+        return bias == Cmp.Bias.LT ? LirOpcodes.DCMPL : LirOpcodes.DCMPG;
+      default:
+        throw new Unreachable("Cmp has unknown type " + type);
+    }
+  }
+
+  public LirBuilder<V, EV> addCmp(NumericType type, Bias bias, V leftValue, V rightValue) {
+    return addTwoValueInstruction(getCmpOpcode(type, bias), leftValue, rightValue);
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
index ed94301..77b9422 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -106,6 +106,18 @@
     onInvokeMethodInstruction(method, arguments);
   }
 
+  public void onInvokeStatic(DexMethod method, List<EV> arguments) {
+    onInvokeMethodInstruction(method, arguments);
+  }
+
+  public void onInvokeInterface(DexMethod method, List<EV> arguments) {
+    onInvokeMethodInstruction(method, arguments);
+  }
+
+  public void onNewInstance(DexType clazz) {
+    onInstruction();
+  }
+
   public void onFieldInstruction(DexField field) {
     onInstruction();
   }
@@ -130,6 +142,11 @@
     onInstruction();
   }
 
+  public void onCmpInstruction(int opcode, EV leftValue, EV rightValue) {
+    assert LirOpcodes.LCMP <= opcode && opcode <= LirOpcodes.DCMPG;
+    onInstruction();
+  }
+
   private DexItem getConstantItem(int index) {
     return code.getConstantItem(index);
   }
@@ -204,6 +221,29 @@
           onInvokeVirtual(target, arguments);
           return;
         }
+      case LirOpcodes.INVOKESTATIC:
+        {
+          DexMethod target = getInvokeInstructionTarget(view);
+          List<EV> arguments = getInvokeInstructionArguments(view);
+          onInvokeStatic(target, arguments);
+          return;
+        }
+      case LirOpcodes.INVOKEINTERFACE:
+        {
+          DexMethod target = getInvokeInstructionTarget(view);
+          List<EV> arguments = getInvokeInstructionArguments(view);
+          onInvokeInterface(target, arguments);
+          return;
+        }
+      case LirOpcodes.NEW:
+        {
+          DexItem item = getConstantItem(view.getNextConstantOperand());
+          if (item instanceof DexType) {
+            onNewInstance((DexType) item);
+            return;
+          }
+          throw new Unimplemented();
+        }
       case LirOpcodes.GETSTATIC:
         {
           DexField field = (DexField) getConstantItem(view.getNextConstantOperand());
@@ -252,6 +292,17 @@
           onDebugLocalWrite(srcIndex);
           return;
         }
+      case LirOpcodes.LCMP:
+      case LirOpcodes.FCMPL:
+      case LirOpcodes.FCMPG:
+      case LirOpcodes.DCMPL:
+      case LirOpcodes.DCMPG:
+        {
+          EV leftValue = getNextValueOperand(view);
+          EV rightValue = getNextValueOperand(view);
+          onCmpInstruction(opcode, leftValue, rightValue);
+          return;
+        }
       default:
         throw new Unimplemented("No dispatch for opcode " + LirOpcodes.toString(opcode));
     }
diff --git a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
index f4a840b..a705fd2 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirPrinter.java
@@ -11,6 +11,7 @@
 import com.android.tools.r8.ir.code.IfType;
 import com.android.tools.r8.ir.code.NumericType;
 import com.android.tools.r8.utils.StringUtils;
+import java.util.Arrays;
 import java.util.List;
 
 public class LirPrinter<EV> extends LirParsedInstructionCallback<EV> {
@@ -60,6 +61,11 @@
     return instructionIndex < 0 ? "--" : ("" + instructionIndex);
   }
 
+  @SafeVarargs
+  private void appendValueArguments(EV... arguments) {
+    appendValueArguments(Arrays.asList(arguments));
+  }
+
   private void appendValueArguments(List<EV> arguments) {
     for (int i = 0; i < arguments.size(); i++) {
       builder.append(fmtValueIndex(arguments.get(i))).append(' ');
@@ -203,4 +209,10 @@
     appendValueArguments(operands);
     builder.append(type);
   }
+
+  @Override
+  public void onCmpInstruction(int opcode, EV leftValue, EV rightValue) {
+    appendOutValue();
+    appendValueArguments(leftValue, rightValue);
+  }
 }