[LIR] Add all arithmetic binary operations.
Bug: b/225838009
Change-Id: I07a33126017af97da28e0a34e64d19445edd66f0
diff --git a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
index 95cdc02..398da41 100644
--- a/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
+++ b/src/main/java/com/android/tools/r8/cf/code/CfArithmeticBinop.java
@@ -120,23 +120,28 @@
}
public int getAsmOpcode() {
+ return getAsmOpcode(opcode, type);
+ }
+
+ public static int getAsmOpcode(Opcode opcode, NumericType type) {
+ int typeOffset = getAsmOpcodeTypeOffset(type);
switch (opcode) {
case Add:
- return Opcodes.IADD + getAsmOpcodeTypeOffset();
+ return Opcodes.IADD + typeOffset;
case Sub:
- return Opcodes.ISUB + getAsmOpcodeTypeOffset();
+ return Opcodes.ISUB + typeOffset;
case Mul:
- return Opcodes.IMUL + getAsmOpcodeTypeOffset();
+ return Opcodes.IMUL + typeOffset;
case Div:
- return Opcodes.IDIV + getAsmOpcodeTypeOffset();
+ return Opcodes.IDIV + typeOffset;
case Rem:
- return Opcodes.IREM + getAsmOpcodeTypeOffset();
+ return Opcodes.IREM + typeOffset;
default:
throw new Unreachable("CfArithmeticBinop has unknown opcode " + opcode);
}
}
- private int getAsmOpcodeTypeOffset() {
+ private static int getAsmOpcodeTypeOffset(NumericType type) {
switch (type) {
case LONG:
return Opcodes.LADD - Opcodes.IADD;
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 cf6039c..f2aa7cf 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
@@ -12,6 +12,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 java.util.function.Function;
public abstract class ArithmeticBinop extends Binop {
@@ -167,4 +168,9 @@
public void buildCf(CfBuilder builder) {
builder.add(new CfArithmeticBinop(getCfOpcode(), type), this);
}
+
+ @Override
+ public void buildLir(LirBuilder<Value, ?> builder) {
+ builder.addArithmeticBinop(getCfOpcode(), type, leftValue(), rightValue());
+ }
}
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 ebaa39c..78e84db 100644
--- a/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
+++ b/src/main/java/com/android/tools/r8/lightir/Lir2IRConverter.java
@@ -12,6 +12,7 @@
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.Add;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.ArrayLength;
import com.android.tools.r8.ir.code.BasicBlock;
@@ -36,14 +37,17 @@
import com.android.tools.r8.ir.code.InvokeSuper;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.MoveException;
+import com.android.tools.r8.ir.code.Mul;
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;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Position.SyntheticPosition;
+import com.android.tools.r8.ir.code.Rem;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.code.StaticGet;
+import com.android.tools.r8.ir.code.Sub;
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
@@ -334,10 +338,33 @@
}
@Override
- public void onDivInt(EV leftValueIndex, EV rightValueIndex) {
+ public void onAdd(NumericType type, EV leftValueIndex, EV rightValueIndex) {
Value dest = getOutValueForNextInstruction(TypeElement.getInt());
- addInstruction(
- new Div(NumericType.INT, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
+ addInstruction(new Add(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
+ }
+
+ @Override
+ public void onSub(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ addInstruction(new Sub(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
+ }
+
+ @Override
+ public void onMul(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ addInstruction(new Mul(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
+ }
+
+ @Override
+ public void onDiv(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ addInstruction(new Div(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
+ }
+
+ @Override
+ public void onRem(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ Value dest = getOutValueForNextInstruction(TypeElement.getInt());
+ addInstruction(new Rem(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
}
@Override
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 37806dd..3edc3c2 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.lightir;
+import com.android.tools.r8.cf.code.CfArithmeticBinop;
+import com.android.tools.r8.cf.code.CfArithmeticBinop.Opcode;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DebugLocalInfo;
@@ -495,4 +497,13 @@
public LirBuilder<V, EV> addCmp(NumericType type, Bias bias, V leftValue, V rightValue) {
return addTwoValueInstruction(getCmpOpcode(type, bias), leftValue, rightValue);
}
+
+ public LirBuilder<V, EV> addArithmeticBinop(
+ Opcode binop, NumericType type, V leftValue, V rightValue) {
+ // The LIR and CF opcodes are the same values, check that the two endpoints match.
+ assert LirOpcodes.IADD == CfArithmeticBinop.getAsmOpcode(Opcode.Add, NumericType.INT);
+ assert LirOpcodes.DREM == CfArithmeticBinop.getAsmOpcode(Opcode.Rem, NumericType.DOUBLE);
+ int opcode = CfArithmeticBinop.getAsmOpcode(binop, type);
+ return addTwoValueInstruction(opcode, 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 96cb7ee..3342eed 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -66,6 +66,66 @@
onInstruction();
}
+ public void onAdd(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ onInstruction();
+ }
+
+ public void onAddInt(EV leftValueIndex, EV rightValueIndex) {
+ onAdd(NumericType.INT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onAddLong(EV leftValueIndex, EV rightValueIndex) {
+ onAdd(NumericType.LONG, leftValueIndex, rightValueIndex);
+ }
+
+ public void onAddFloat(EV leftValueIndex, EV rightValueIndex) {
+ onAdd(NumericType.FLOAT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onAddDouble(EV leftValueIndex, EV rightValueIndex) {
+ onAdd(NumericType.DOUBLE, leftValueIndex, rightValueIndex);
+ }
+
+ public void onSub(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ onInstruction();
+ }
+
+ public void onSubInt(EV leftValueIndex, EV rightValueIndex) {
+ onSub(NumericType.INT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onSubLong(EV leftValueIndex, EV rightValueIndex) {
+ onSub(NumericType.LONG, leftValueIndex, rightValueIndex);
+ }
+
+ public void onSubFloat(EV leftValueIndex, EV rightValueIndex) {
+ onSub(NumericType.FLOAT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onSubDouble(EV leftValueIndex, EV rightValueIndex) {
+ onSub(NumericType.DOUBLE, leftValueIndex, rightValueIndex);
+ }
+
+ public void onMul(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ onInstruction();
+ }
+
+ public void onMulInt(EV leftValueIndex, EV rightValueIndex) {
+ onMul(NumericType.INT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onMulLong(EV leftValueIndex, EV rightValueIndex) {
+ onMul(NumericType.LONG, leftValueIndex, rightValueIndex);
+ }
+
+ public void onMulFloat(EV leftValueIndex, EV rightValueIndex) {
+ onMul(NumericType.FLOAT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onMulDouble(EV leftValueIndex, EV rightValueIndex) {
+ onMul(NumericType.DOUBLE, leftValueIndex, rightValueIndex);
+ }
+
public void onDiv(NumericType type, EV leftValueIndex, EV rightValueIndex) {
onInstruction();
}
@@ -74,6 +134,38 @@
onDiv(NumericType.INT, leftValueIndex, rightValueIndex);
}
+ public void onDivLong(EV leftValueIndex, EV rightValueIndex) {
+ onDiv(NumericType.LONG, leftValueIndex, rightValueIndex);
+ }
+
+ public void onDivFloat(EV leftValueIndex, EV rightValueIndex) {
+ onDiv(NumericType.FLOAT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onDivDouble(EV leftValueIndex, EV rightValueIndex) {
+ onDiv(NumericType.DOUBLE, leftValueIndex, rightValueIndex);
+ }
+
+ public void onRem(NumericType type, EV leftValueIndex, EV rightValueIndex) {
+ onInstruction();
+ }
+
+ public void onRemInt(EV leftValueIndex, EV rightValueIndex) {
+ onRem(NumericType.INT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onRemLong(EV leftValueIndex, EV rightValueIndex) {
+ onRem(NumericType.LONG, leftValueIndex, rightValueIndex);
+ }
+
+ public void onRemFloat(EV leftValueIndex, EV rightValueIndex) {
+ onRem(NumericType.FLOAT, leftValueIndex, rightValueIndex);
+ }
+
+ public void onRemDouble(EV leftValueIndex, EV rightValueIndex) {
+ onRem(NumericType.DOUBLE, leftValueIndex, rightValueIndex);
+ }
+
public void onIf(IfType ifKind, int blockIndex, EV valueIndex) {
onInstruction();
}
@@ -197,6 +289,90 @@
onConstInt(value);
return;
}
+ case LirOpcodes.IADD:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onAddInt(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.LADD:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onAddLong(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.FADD:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onAddFloat(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.DADD:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onAddDouble(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.ISUB:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onSubInt(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.LSUB:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onSubLong(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.FSUB:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onSubFloat(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.DSUB:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onSubDouble(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.IMUL:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onMulInt(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.LMUL:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onMulLong(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.FMUL:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onMulFloat(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.DMUL:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onMulDouble(leftValueIndex, rightValueIndex);
+ return;
+ }
case LirOpcodes.IDIV:
{
EV leftValueIndex = getNextValueOperand(view);
@@ -204,6 +380,55 @@
onDivInt(leftValueIndex, rightValueIndex);
return;
}
+ case LirOpcodes.LDIV:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onDivLong(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.FDIV:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onDivFloat(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.DDIV:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onDivDouble(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.IREM:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onRemInt(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.LREM:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onRemLong(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.FREM:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onRemFloat(leftValueIndex, rightValueIndex);
+ return;
+ }
+ case LirOpcodes.DREM:
+ {
+ EV leftValueIndex = getNextValueOperand(view);
+ EV rightValueIndex = getNextValueOperand(view);
+ onRemDouble(leftValueIndex, rightValueIndex);
+ return;
+ }
case LirOpcodes.IFNE:
{
int blockIndex = view.getNextBlockOperand();