1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 public class Main { 18 19 /// CHECK-START: java.lang.Integer Main.foo(int) disassembly (after) 20 /// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf 21 /// CHECK: pAllocObjectInitialized 22 /// CHECK: Return [<<Integer>>] foo(int a)23 public static Integer foo(int a) { 24 return Integer.valueOf(a); 25 } 26 27 /// CHECK-START: java.lang.Integer Main.foo2() disassembly (after) 28 /// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf 29 /// CHECK-NOT: pAllocObjectInitialized 30 /// CHECK: Return [<<Integer>>] foo2()31 public static Integer foo2() { 32 return Integer.valueOf(-42); 33 } 34 35 /// CHECK-START: java.lang.Integer Main.foo3() disassembly (after) 36 /// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf 37 /// CHECK-NOT: pAllocObjectInitialized 38 /// CHECK: Return [<<Integer>>] foo3()39 public static Integer foo3() { 40 return Integer.valueOf(42); 41 } 42 43 /// CHECK-START: java.lang.Integer Main.foo4() disassembly (after) 44 /// CHECK: <<Integer:l\d+>> InvokeStaticOrDirect method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf 45 /// CHECK: pAllocObjectInitialized 46 /// CHECK: Return [<<Integer>>] foo4()47 public static Integer foo4() { 48 return Integer.valueOf(55555); 49 } 50 51 /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) builder (after) 52 /// CHECK: <<Input:b\d+>> ParameterValue 53 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 54 /// CHECK-NOT: NullCheck [<<Boxed>>] 55 /// CHECK: <<Unboxed:b\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Byte.byteValue 56 /// CHECK: Return [<<Unboxed>>] 57 58 /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) inliner (after) 59 /// CHECK: <<Input:b\d+>> ParameterValue 60 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 61 /// CHECK: <<Unboxed:b\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Byte.value 62 /// CHECK: Return [<<Unboxed>>] 63 64 /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) instruction_simplifier$after_inlining (after) 65 /// CHECK: <<Input:b\d+>> ParameterValue 66 /// CHECK: Return [<<Input>>] 67 68 /// CHECK-START: byte Main.$noinline$boxUnboxByte(byte) dead_code_elimination$after_inlining (after) 69 /// CHECK-NOT: InvokeStaticOrDirect 70 /// CHECK-NOT: InstanceFieldGet 71 $noinline$boxUnboxByte(byte value)72 public static byte $noinline$boxUnboxByte(byte value) { 73 return Byte.valueOf(value).byteValue(); 74 } 75 76 /// CHECK-START: short Main.$noinline$boxUnboxShort(short) builder (after) 77 /// CHECK: <<Input:s\d+>> ParameterValue 78 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Short.valueOf intrinsic:ShortValueOf 79 /// CHECK-NOT: NullCheck [<<Boxed>>] 80 /// CHECK: <<Unboxed:s\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Short.shortValue 81 /// CHECK: Return [<<Unboxed>>] 82 83 /// CHECK-START: short Main.$noinline$boxUnboxShort(short) inliner (after) 84 /// CHECK: <<Input:s\d+>> ParameterValue 85 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Short.valueOf intrinsic:ShortValueOf 86 /// CHECK: <<Unboxed:s\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Short.value 87 /// CHECK: Return [<<Unboxed>>] 88 89 /// CHECK-START: short Main.$noinline$boxUnboxShort(short) instruction_simplifier$after_inlining (after) 90 /// CHECK: <<Input:s\d+>> ParameterValue 91 /// CHECK: Return [<<Input>>] 92 93 /// CHECK-START: short Main.$noinline$boxUnboxShort(short) dead_code_elimination$after_inlining (after) 94 /// CHECK-NOT: InvokeStaticOrDirect 95 /// CHECK-NOT: InstanceFieldGet 96 $noinline$boxUnboxShort(short value)97 public static short $noinline$boxUnboxShort(short value) { 98 return Short.valueOf(value).shortValue(); 99 } 100 101 /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) builder (after) 102 /// CHECK: <<Input:c\d+>> ParameterValue 103 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Character.valueOf intrinsic:CharacterValueOf 104 /// CHECK-NOT: NullCheck [<<Boxed>>] 105 /// CHECK: <<Unboxed:c\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Character.charValue 106 /// CHECK: Return [<<Unboxed>>] 107 108 /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) inliner (after) 109 /// CHECK: <<Input:c\d+>> ParameterValue 110 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Character.valueOf intrinsic:CharacterValueOf 111 /// CHECK: <<Unboxed:c\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Character.value 112 /// CHECK: Return [<<Unboxed>>] 113 114 /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) instruction_simplifier$after_inlining (after) 115 /// CHECK: <<Input:c\d+>> ParameterValue 116 /// CHECK: Return [<<Input>>] 117 118 /// CHECK-START: char Main.$noinline$boxUnboxCharacter(char) dead_code_elimination$after_inlining (after) 119 /// CHECK-NOT: InvokeStaticOrDirect 120 /// CHECK-NOT: InstanceFieldGet 121 $noinline$boxUnboxCharacter(char value)122 public static char $noinline$boxUnboxCharacter(char value) { 123 return Character.valueOf(value).charValue(); 124 } 125 126 /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) builder (after) 127 /// CHECK: <<Input:i\d+>> ParameterValue 128 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf 129 /// CHECK-NOT: NullCheck [<<Boxed>>] 130 /// CHECK: <<Unboxed:i\d+>> InvokeVirtual [<<Boxed>>] method_name:java.lang.Integer.intValue 131 /// CHECK: Return [<<Unboxed>>] 132 133 /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) inliner (after) 134 /// CHECK: <<Input:i\d+>> ParameterValue 135 /// CHECK: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Integer.valueOf intrinsic:IntegerValueOf 136 /// CHECK: <<Unboxed:i\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Integer.value 137 /// CHECK: Return [<<Unboxed>>] 138 139 /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) instruction_simplifier$after_inlining (after) 140 /// CHECK: <<Input:i\d+>> ParameterValue 141 /// CHECK: Return [<<Input>>] 142 143 /// CHECK-START: int Main.$noinline$boxUnboxInteger(int) dead_code_elimination$after_inlining (after) 144 /// CHECK-NOT: InvokeStaticOrDirect 145 /// CHECK-NOT: InstanceFieldGet 146 $noinline$boxUnboxInteger(int value)147 public static int $noinline$boxUnboxInteger(int value) { 148 return Integer.valueOf(value).intValue(); 149 } 150 151 /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) builder (after) 152 /// CHECK-DAG: <<Input:b\d+>> ParameterValue 153 /// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 154 /// CHECK-DAG: <<Phi:l\d+>> Phi 155 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>] 156 /// CHECK-DAG: <<Unboxed:b\d+>> InvokeVirtual [<<NC>>] method_name:java.lang.Byte.byteValue 157 /// CHECK-DAG: <<And:i\d+>> And 158 /// CHECK-DAG: Return [<<And>>] 159 160 /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier (after) 161 /// CHECK-DAG: <<Input:b\d+>> ParameterValue 162 /// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 163 /// CHECK-DAG: <<Phi:l\d+>> Phi 164 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>] 165 /// CHECK-DAG: <<Unboxed:b\d+>> InvokeVirtual [<<NC>>] method_name:java.lang.Byte.byteValue 166 /// CHECK-DAG: <<Conv:a\d+>> TypeConversion [<<Unboxed>>] 167 /// CHECK-DAG: Return [<<Conv>>] 168 169 /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) inliner (after) 170 /// CHECK-DAG: <<Input:b\d+>> ParameterValue 171 /// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 172 /// CHECK-DAG: <<Phi:l\d+>> Phi 173 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>] 174 /// CHECK-DAG: <<Unboxed:b\d+>> InstanceFieldGet [<<NC>>] field_name:java.lang.Byte.value 175 /// CHECK-DAG: <<Conv:a\d+>> TypeConversion [<<Unboxed>>] 176 /// CHECK-DAG: Return [<<Conv>>] 177 178 /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier$after_inlining (after) 179 /// CHECK-DAG: <<Input:b\d+>> ParameterValue 180 /// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 181 /// CHECK-DAG: <<Phi:l\d+>> Phi 182 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Phi>>] 183 /// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<NC>>] field_name:java.lang.Byte.value 184 /// CHECK-DAG: Return [<<Conv>>] 185 186 /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) dead_code_elimination$after_inlining (after) 187 /// CHECK-DAG: <<Input:b\d+>> ParameterValue 188 /// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 189 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<Boxed>>] 190 /// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<NC>>] field_name:java.lang.Byte.value 191 /// CHECK-DAG: Return [<<Conv>>] 192 193 /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) instruction_simplifier$after_gvn (after) 194 /// CHECK-DAG: <<Input:b\d+>> ParameterValue 195 /// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 196 /// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Byte.value 197 /// CHECK-DAG: Return [<<Conv>>] 198 199 /// CHECK-START: int Main.$noinline$boxUnboxByteAsUint8(byte) disassembly (after) 200 /// CHECK-DAG: <<Input:b\d+>> ParameterValue 201 /// CHECK-DAG: <<Boxed:l\d+>> InvokeStaticOrDirect [<<Input>>{{(,[ij]\d+)?}}] method_name:java.lang.Byte.valueOf intrinsic:ByteValueOf 202 /// CHECK-DAG: <<Conv:a\d+>> InstanceFieldGet [<<Boxed>>] field_name:java.lang.Byte.value 203 /// CHECK-DAG: Return [<<Conv>>] 204 $noinline$boxUnboxByteAsUint8(byte value)205 public static int $noinline$boxUnboxByteAsUint8(byte value) { 206 Byte boxed = Byte.valueOf(value); 207 208 // Hide the unboxing from the initial instruction simplifier pass or the one after inlining, 209 // so that after inlining we can merge the `TypeConversion` into `InstanceFieldGet` with 210 // a modified type. The Phi shall be eliminated by `dead_code_elimination$after_inlining`. 211 // The null check that shall be eliminated by `instruction_simplifier$after_gvn (after)` 212 Byte merged = $inline$returnTrue() ? boxed : null; 213 214 // Due to the type mismatch, we shall not simplify the unboxing. The boxing and unboxing 215 // shall be kept during subsequent simplifier passes all the way to the disassembly. 216 return merged.byteValue() & 0xff; 217 } 218 $inline$returnTrue()219 public static boolean $inline$returnTrue() { 220 return true; 221 } 222 main(String[] args)223 public static void main(String[] args) { 224 assertEqual("42", foo(intField)); 225 assertEqual(foo(intField), foo(intField2)); 226 assertEqual("-42", foo2()); 227 assertEqual("42", foo3()); 228 assertEqual("55555", foo4()); 229 assertEqual("55555", foo(intField3)); 230 assertEqual("-129", foo(intFieldMinus129)); 231 assertEqual("-128", foo(intFieldMinus128)); 232 assertEqual(foo(intFieldMinus128), foo(intFieldMinus128)); 233 assertEqual("-127", foo(intFieldMinus127)); 234 assertEqual(foo(intFieldMinus127), foo(intFieldMinus127)); 235 assertEqual("126", foo(intField126)); 236 assertEqual(foo(intField126), foo(intField126)); 237 assertEqual("127", foo(intField127)); 238 assertEqual(foo(intField127), foo(intField127)); 239 assertEqual("128", foo(intField128)); 240 241 assertEqual(42, (int) $noinline$boxUnboxByte((byte) 42)); 242 assertEqual(-42, (int) $noinline$boxUnboxByte((byte) -42)); 243 assertEqual(42, (int) $noinline$boxUnboxShort((short) 42)); 244 assertEqual(-42, (int) $noinline$boxUnboxShort((short) -42)); 245 assertEqual((int) (char) 42, (int) $noinline$boxUnboxCharacter((char) 42)); 246 assertEqual((int) (char) -42, (int) $noinline$boxUnboxCharacter((char) -42)); 247 assertEqual(42, $noinline$boxUnboxInteger(42)); 248 assertEqual(-42, $noinline$boxUnboxInteger(-42)); 249 250 assertEqual(42, $noinline$boxUnboxByteAsUint8((byte) 42)); 251 assertEqual(-42 & 0xff, $noinline$boxUnboxByteAsUint8((byte) -42)); 252 } 253 assertEqual(String a, Integer b)254 static void assertEqual(String a, Integer b) { 255 if (!a.equals(b.toString())) { 256 throw new Error("Expected " + a + ", got " + b); 257 } 258 } 259 assertEqual(Integer a, Integer b)260 static void assertEqual(Integer a, Integer b) { 261 if (a != b) { 262 throw new Error("Expected " + a + ", got " + b); 263 } 264 } 265 assertEqual(int a, int b)266 static void assertEqual(int a, int b) { 267 if (a != b) { 268 throw new Error("Expected " + a + ", got " + b); 269 } 270 } 271 272 static int intField = 42; 273 static int intField2 = 42; 274 static int intField3 = 55555; 275 276 // Edge cases. 277 static int intFieldMinus129 = -129; 278 static int intFieldMinus128 = -128; 279 static int intFieldMinus127 = -127; 280 static int intField126 = 126; 281 static int intField127 = 127; 282 static int intField128 = 128; 283 } 284