blob: cf0d7d8774f534fd851486a704026eec4d4986c2 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
public class Main {
/// CHECK-START: java.lang.Integer Main.foo(int) disassembly (after)
/// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf
/// CHECK: pAllocObjectInitialized
/// CHECK: Return [<<Integer>>]
public static Integer foo(int a) {
return Integer.valueOf(a);
}
/// CHECK-START: java.lang.Integer Main.foo2() disassembly (after)
/// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf
/// CHECK-NOT: pAllocObjectInitialized
/// CHECK: Return [<<Integer>>]
public static Integer foo2() {
return Integer.valueOf(-42);
}
/// CHECK-START: java.lang.Integer Main.foo3() disassembly (after)
/// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf
/// CHECK-NOT: pAllocObjectInitialized
/// CHECK: Return [<<Integer>>]
public static Integer foo3() {
return Integer.valueOf(42);
}
/// CHECK-START: java.lang.Integer Main.foo4() disassembly (after)
/// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf
/// CHECK: pAllocObjectInitialized
/// CHECK: Return [<<Integer>>]
public static Integer foo4() {
return Integer.valueOf(55555);
}
/// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) builder (after)
/// CHECK: <<Input:b\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-NOT: NullCheck [<<Boxed>>]
/// CHECK: <<Unboxed:b\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Byte.byteValue
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) inliner (after)
/// CHECK: <<Input:b\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK: <<Unboxed:b\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Byte.value
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) instruction_simplifier$after_inlining (after)
/// CHECK: <<Input:b\d+>> ParameterValue
/// CHECK: Return [<<Input>>]
/// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) dead_code_elimination$after_inlining (after)
/// CHECK-NOT: InvokeStaticOrDirect
/// CHECK-NOT: InstanceFieldGet
public static byte $noinline$boxUnboxByte(byte value) {
return Byte.valueOf(value).byteValue();
}
/// CHECK-START: short Main.$noinline$boxUnboxShort(short) builder (after)
/// CHECK: <<Input:s\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Short.valueOf intrinsic:ShortValueOf
/// CHECK-NOT: NullCheck [<<Boxed>>]
/// CHECK: <<Unboxed:s\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Short.shortValue
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: short Main.$noinline$boxUnboxShort(short) inliner (after)
/// CHECK: <<Input:s\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Short.valueOf intrinsic:ShortValueOf
/// CHECK: <<Unboxed:s\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Short.value
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: short Main.$noinline$boxUnboxShort(short) instruction_simplifier$after_inlining (after)
/// CHECK: <<Input:s\d+>> ParameterValue
/// CHECK: Return [<<Input>>]
/// CHECK-START: short Main.$noinline$boxUnboxShort(short) dead_code_elimination$after_inlining (after)
/// CHECK-NOT: InvokeStaticOrDirect
/// CHECK-NOT: InstanceFieldGet
public static short $noinline$boxUnboxShort(short value) {
return Short.valueOf(value).shortValue();
}
/// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) builder (after)
/// CHECK: <<Input:c\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Character.valueOf intrinsic:CharacterValueOf
/// CHECK-NOT: NullCheck [<<Boxed>>]
/// CHECK: <<Unboxed:c\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Character.charValue
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) inliner (after)
/// CHECK: <<Input:c\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Character.valueOf intrinsic:CharacterValueOf
/// CHECK: <<Unboxed:c\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Character.value
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) instruction_simplifier$after_inlining (after)
/// CHECK: <<Input:c\d+>> ParameterValue
/// CHECK: Return [<<Input>>]
/// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) dead_code_elimination$after_inlining (after)
/// CHECK-NOT: InvokeStaticOrDirect
/// CHECK-NOT: InstanceFieldGet
public static char $noinline$boxUnboxCharacter(char value) {
return Character.valueOf(value).charValue();
}
/// CHECK-START: int Main.$noinline$boxUnboxInteger(int) builder (after)
/// CHECK: <<Input:i\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf
/// CHECK-NOT: NullCheck [<<Boxed>>]
/// CHECK: <<Unboxed:i\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Integer.intValue
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: int Main.$noinline$boxUnboxInteger(int) inliner (after)
/// CHECK: <<Input:i\d+>> ParameterValue
/// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf
/// CHECK: <<Unboxed:i\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Integer.value
/// CHECK: Return [<<Unboxed>>]
/// CHECK-START: int Main.$noinline$boxUnboxInteger(int) instruction_simplifier$after_inlining (after)
/// CHECK: <<Input:i\d+>> ParameterValue
/// CHECK: Return [<<Input>>]
/// CHECK-START: int Main.$noinline$boxUnboxInteger(int) dead_code_elimination$after_inlining (after)
/// CHECK-NOT: InvokeStaticOrDirect
/// CHECK-NOT: InstanceFieldGet
public static int $noinline$boxUnboxInteger(int value) {
return Integer.valueOf(value).intValue();
}
/// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) builder (after)
/// CHECK-DAG: <<Input:b\d+>> ParameterValue
/// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-DAG: <<Phi:l\d+>> Phi
/// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>]
/// CHECK-DAG: <<Unboxed:b\d+>> InvokeVirtual [<<NC>>] method_name:java.lang.Byte.byteValue
/// CHECK-DAG: <<And:i\d+>> And
/// CHECK-DAG: Return [<<And>>]
/// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier (after)
/// CHECK-DAG: <<Input:b\d+>> ParameterValue
/// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-DAG: <<Phi:l\d+>> Phi
/// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>]
/// CHECK-DAG: <<Unboxed:b\d+>> InvokeVirtual [<<NC>>] method_name:java.lang.Byte.byteValue
/// CHECK-DAG: <<Conv:a\d+>> TypeConversion [<<Unboxed>>]
/// CHECK-DAG: Return [<<Conv>>]
/// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) inliner (after)
/// CHECK-DAG: <<Input:b\d+>> ParameterValue
/// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-DAG: <<Phi:l\d+>> Phi
/// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>]
/// CHECK-DAG: <<Unboxed:b\d+>> InstanceFieldGet [<<NC>>] field_name:java.lang.Byte.value
/// CHECK-DAG: <<Conv:a\d+>> TypeConversion [<<Unboxed>>]
/// CHECK-DAG: Return [<<Conv>>]
/// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier$after_inlining (after)
/// CHECK-DAG: <<Input:b\d+>> ParameterValue
/// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-DAG: <<Phi:l\d+>> Phi
/// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>]
/// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<NC>>] field_name:java.lang.Byte.value
/// CHECK-DAG: Return [<<Conv>>]
/// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) dead_code_elimination$after_inlining (after)
/// CHECK-DAG: <<Input:b\d+>> ParameterValue
/// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Boxed>>]
/// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<NC>>] field_name:java.lang.Byte.value
/// CHECK-DAG: Return [<<Conv>>]
/// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier$after_gvn (after)
/// CHECK-DAG: <<Input:b\d+>> ParameterValue
/// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Byte.value
/// CHECK-DAG: Return [<<Conv>>]
/// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) disassembly (after)
/// CHECK-DAG: <<Input:b\d+>> ParameterValue
/// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf
/// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Byte.value
/// CHECK-DAG: Return [<<Conv>>]
public static int $noinline$boxUnboxByteAsUint8(byte value) {
Byte boxed = Byte.valueOf(value);
// Hide the unboxing from the initial instruction simplifier pass or the one after inlining,
// so that after inlining we can merge the `TypeConversion` into `InstanceFieldGet` with
// a modified type. The Phi shall be eliminated by `dead_code_elimination$after_inlining`.
// The null check that shall be eliminated by `instruction_simplifier$after_gvn (after)`
Byte merged = $inline$returnTrue() ? boxed : null;
// Due to the type mismatch, we shall not simplify the unboxing. The boxing and unboxing
// shall be kept during subsequent simplifier passes all the way to the disassembly.
return merged.byteValue() & 0xff;
}
public static boolean $inline$returnTrue() {
return true;
}
public static void main(String[] args) {
assertEqual("42", foo(intField));
assertEqual(foo(intField), foo(intField2));
assertEqual("-42", foo2());
assertEqual("42", foo3());
assertEqual("55555", foo4());
assertEqual("55555", foo(intField3));
assertEqual("-129", foo(intFieldMinus129));
assertEqual("-128", foo(intFieldMinus128));
assertEqual(foo(intFieldMinus128), foo(intFieldMinus128));
assertEqual("-127", foo(intFieldMinus127));
assertEqual(foo(intFieldMinus127), foo(intFieldMinus127));
assertEqual("126", foo(intField126));
assertEqual(foo(intField126), foo(intField126));
assertEqual("127", foo(intField127));
assertEqual(foo(intField127), foo(intField127));
assertEqual("128", foo(intField128));
assertEqual(42, (int) $noinline$boxUnboxByte((byte) 42));
assertEqual(-42, (int) $noinline$boxUnboxByte((byte) -42));
assertEqual(42, (int) $noinline$boxUnboxShort((short) 42));
assertEqual(-42, (int) $noinline$boxUnboxShort((short) -42));
assertEqual((int) (char) 42, (int) $noinline$boxUnboxCharacter((char) 42));
assertEqual((int) (char) -42, (int) $noinline$boxUnboxCharacter((char) -42));
assertEqual(42, $noinline$boxUnboxInteger(42));
assertEqual(-42, $noinline$boxUnboxInteger(-42));
assertEqual(42, $noinline$boxUnboxByteAsUint8((byte) 42));
assertEqual(-42 & 0xff, $noinline$boxUnboxByteAsUint8((byte) -42));
}
static void assertEqual(String a, Integer b) {
if (!a.equals(b.toString())) {
throw new Error("Expected " + a + ", got " + b);
}
}
static void assertEqual(Integer a, Integer b) {
if (a != b) {
throw new Error("Expected " + a + ", got " + b);
}
}
static void assertEqual(int a, int b) {
if (a != b) {
throw new Error("Expected " + a + ", got " + b);
}
}
static int intField = 42;
static int intField2 = 42;
static int intField3 = 55555;
// Edge cases.
static int intFieldMinus129 = -129;
static int intFieldMinus128 = -128;
static int intFieldMinus127 = -127;
static int intField126 = 126;
static int intField127 = 127;
static int intField128 = 128;
}