[LIR] Add all constant number instructions.
Bug: b/225838009
Change-Id: Ia673b084b5c1d8bb1fc8b4c99677fc009dd41835
diff --git a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
index 5d34483..dc174ff 100644
--- a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
+++ b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
@@ -17,6 +17,10 @@
return value & 0xFF;
}
+ private static int truncateToU1(long value) {
+ return (int) value & 0xFF;
+ }
+
public static int ensureU1(int value) {
assert isU1(value);
return truncateToU1(value);
@@ -47,6 +51,35 @@
return value;
}
+ public static int longEncodingSize(long value) {
+ return 8;
+ }
+
+ public static void writeEncodedLong(long value, ByteWriter writer) {
+ assert 8 == longEncodingSize(value);
+ writer.put(truncateToU1(value >> 56));
+ writer.put(truncateToU1(value >> 48));
+ writer.put(truncateToU1(value >> 40));
+ writer.put(truncateToU1(value >> 32));
+ writer.put(truncateToU1(value >> 24));
+ writer.put(truncateToU1(value >> 16));
+ writer.put(truncateToU1(value >> 8));
+ writer.put(truncateToU1(value));
+ }
+
+ public static long readEncodedLong(ByteIterator iterator) {
+ assert 8 == longEncodingSize(0);
+ long value = ((long) truncateToU1(iterator.nextByte())) << 56;
+ value |= ((long) truncateToU1(iterator.nextByte())) << 48;
+ value |= ((long) truncateToU1(iterator.nextByte())) << 40;
+ value |= ((long) truncateToU1(iterator.nextByte())) << 32;
+ value |= ((long) truncateToU1(iterator.nextByte())) << 24;
+ value |= ((long) truncateToU1(iterator.nextByte())) << 16;
+ value |= ((long) truncateToU1(iterator.nextByte())) << 8;
+ value |= truncateToU1(iterator.nextByte());
+ return value;
+ }
+
public static boolean isU2(int value) {
return (value >= 0) && (value <= 0xFFFF);
}
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 3edc3c2..024d6d7 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -44,6 +44,11 @@
/** Builder for constructing LIR code from IR. */
public class LirBuilder<V, EV> {
+ private static final int FLOAT_0 = Float.floatToRawIntBits(0);
+ private static final int FLOAT_1 = Float.floatToRawIntBits(1);
+ private static final int FLOAT_2 = Float.floatToRawIntBits(2);
+ private static final long DOUBLE_0 = Double.doubleToRawLongBits(0);
+ private static final long DOUBLE_1 = Double.doubleToRawLongBits(1);
private final DexItemFactory factory;
private final ByteArrayWriter byteWriter = new ByteArrayWriter();
@@ -256,6 +261,48 @@
return this;
}
+ public LirBuilder<V, EV> addConstFloat(int value) {
+ if (value == FLOAT_0) {
+ return addNoOperandInstruction(LirOpcodes.FCONST_0);
+ }
+ if (value == FLOAT_1) {
+ return addNoOperandInstruction(LirOpcodes.FCONST_1);
+ }
+ if (value == FLOAT_2) {
+ return addNoOperandInstruction(LirOpcodes.FCONST_2);
+ }
+ advanceInstructionState();
+ writer.writeInstruction(LirOpcodes.FCONST, ByteUtils.intEncodingSize(value));
+ ByteUtils.writeEncodedInt(value, writer::writeOperand);
+ return this;
+ }
+
+ public LirBuilder<V, EV> addConstLong(long value) {
+ if (value == 0) {
+ return addNoOperandInstruction(LirOpcodes.LCONST_0);
+ }
+ if (value == 1) {
+ return addNoOperandInstruction(LirOpcodes.LCONST_1);
+ }
+ advanceInstructionState();
+ writer.writeInstruction(LirOpcodes.LCONST, ByteUtils.longEncodingSize(value));
+ ByteUtils.writeEncodedLong(value, writer::writeOperand);
+ return this;
+ }
+
+ public LirBuilder<V, EV> addConstDouble(long value) {
+ if (value == DOUBLE_0) {
+ return addNoOperandInstruction(LirOpcodes.DCONST_0);
+ }
+ if (value == DOUBLE_1) {
+ return addNoOperandInstruction(LirOpcodes.DCONST_1);
+ }
+ advanceInstructionState();
+ writer.writeInstruction(LirOpcodes.DCONST, ByteUtils.longEncodingSize(value));
+ ByteUtils.writeEncodedLong(value, writer::writeOperand);
+ return this;
+ }
+
public LirBuilder<V, EV> addConstNumber(ValueType type, long value) {
switch (type) {
case OBJECT:
@@ -263,8 +310,11 @@
case INT:
return addConstInt((int) value);
case FLOAT:
+ return addConstFloat((int) value);
case LONG:
+ return addConstLong(value);
case DOUBLE:
+ return addConstDouble(value);
default:
throw new Unimplemented();
}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirInstructionView.java b/src/main/java/com/android/tools/r8/lightir/LirInstructionView.java
index 3eef40d..546da90 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirInstructionView.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirInstructionView.java
@@ -30,6 +30,9 @@
/** Get the next operand as an encoded integer */
int getNextIntegerOperand();
+ /** Get the next operand as an encoded long */
+ long getNextLongOperand();
+
/** Get the next operand as a constant-pool index. */
int getNextConstantOperand();
diff --git a/src/main/java/com/android/tools/r8/lightir/LirIterator.java b/src/main/java/com/android/tools/r8/lightir/LirIterator.java
index dd29c93..84eaee6 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirIterator.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirIterator.java
@@ -88,6 +88,12 @@
}
@Override
+ public long getNextLongOperand() {
+ assert hasMoreOperands();
+ return u8();
+ }
+
+ @Override
public int getNextConstantOperand() {
return getNextIntegerOperand();
}
@@ -116,4 +122,9 @@
currentByteIndex += 4;
return ByteUtils.readEncodedInt(iterator);
}
+
+ private long u8() {
+ currentByteIndex += 8;
+ return ByteUtils.readEncodedLong(iterator);
+ }
}
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 3342eed..fd7bf56 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -62,6 +62,18 @@
onConstNumber(NumericType.INT, value);
}
+ public void onConstFloat(int value) {
+ onConstNumber(NumericType.FLOAT, value);
+ }
+
+ public void onConstLong(long value) {
+ onConstNumber(NumericType.LONG, value);
+ }
+
+ public void onConstDouble(long value) {
+ onConstNumber(NumericType.DOUBLE, value);
+ }
+
public void onConstString(DexString string) {
onInstruction();
}
@@ -289,6 +301,51 @@
onConstInt(value);
return;
}
+ case LirOpcodes.FCONST_0:
+ case LirOpcodes.FCONST_1:
+ case LirOpcodes.FCONST_2:
+ {
+ float value = opcode - LirOpcodes.FCONST_0;
+ onConstFloat(Float.floatToRawIntBits(value));
+ return;
+ }
+ case LirOpcodes.FCONST:
+ {
+ int value = view.getNextIntegerOperand();
+ onConstFloat(value);
+ return;
+ }
+ case LirOpcodes.LCONST_0:
+ {
+ onConstLong(0);
+ return;
+ }
+ case LirOpcodes.LCONST_1:
+ {
+ onConstLong(1);
+ return;
+ }
+ case LirOpcodes.LCONST:
+ {
+ long value = view.getNextLongOperand();
+ onConstLong(value);
+ return;
+ }
+ case LirOpcodes.DCONST_0:
+ {
+ onConstDouble(Double.doubleToRawLongBits(0));
+ return;
+ }
+ case LirOpcodes.DCONST_1:
+ {
+ onConstDouble(Double.doubleToRawLongBits(1));
+ }
+ case LirOpcodes.DCONST:
+ {
+ long value = view.getNextLongOperand();
+ onConstDouble(value);
+ return;
+ }
case LirOpcodes.IADD:
{
EV leftValueIndex = getNextValueOperand(view);