# 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. .class public LSmaliTests; .super Ljava/lang/Object; ## CHECK-START: void SmaliTests.bar() load_store_elimination (after) ## CHECK-DAG: <> NullConstant ## CHECK-DAG: <> BoundType [<>] ## CHECK-DAG: <> NullCheck [<>] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> NullCheck [<>] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] .method public static bar()V .registers 7 .prologue const/4 v6, 0x3 const/4 v5, 0x2 const/4 v4, 0x1 const/4 v3, 0x0 # We create multiple accesses that will lead the bounds check # elimination pass to add a HDeoptimize. Not having the bounds check helped # the load store elimination think it could merge two ArrayGet with different # types. # String[] array = (String[])getNull(); invoke-static {}, LMain;->getNull()Ljava/lang/Object; move-result-object v0 check-cast v0, [Ljava/lang/String; # objectField = array[0]; aget-object v2, v0, v3 sput-object v2, LMain;->objectField:Ljava/lang/Object; # objectField = array[1]; aget-object v2, v0, v4 sput-object v2, LMain;->objectField:Ljava/lang/Object; # objectField = array[2]; aget-object v2, v0, v5 sput-object v2, LMain;->objectField:Ljava/lang/Object; # objectField = array[3]; aget-object v2, v0, v6 sput-object v2, LMain;->objectField:Ljava/lang/Object; # long[] longArray = getLongArray(); invoke-static {}, LMain;->getLongArray()[J move-result-object v1 # longField = longArray[0]; aget-wide v2, v1, v3 sput-wide v2, LMain;->longField:J # longField = longArray[1]; aget-wide v2, v1, v4 sput-wide v2, LMain;->longField:J # longField = longArray[2]; aget-wide v2, v1, v5 sput-wide v2, LMain;->longField:J # longField = longArray[3]; aget-wide v2, v1, v6 sput-wide v2, LMain;->longField:J return-void .end method # This is indentical to bar() except that it has two check-casts # that DX tends to generate. ## CHECK-START: void SmaliTests.bar2() load_store_elimination (after) ## CHECK-DAG: <> NullConstant ## CHECK-DAG: <> BoundType [<>] ## CHECK-DAG: <> BoundType [<>] ## CHECK-DAG: <> NullCheck [<>] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> NullCheck [<>] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] ## CHECK-DAG: <> ArrayGet [<>,{{i\d+}}] .method public static bar2()V .registers 7 .prologue const/4 v6, 0x3 const/4 v5, 0x2 const/4 v4, 0x1 const/4 v3, 0x0 # We create multiple accesses that will lead the bounds check # elimination pass to add a HDeoptimize. Not having the bounds check helped # the load store elimination think it could merge two ArrayGet with different # types. # String[] array = (String[])getNull(); invoke-static {}, LMain;->getNull()Ljava/lang/Object; move-result-object v2 check-cast v2, [Ljava/lang/String; move-object v0, v2 check-cast v0, [Ljava/lang/String; # objectField = array[0]; aget-object v2, v0, v3 sput-object v2, LMain;->objectField:Ljava/lang/Object; # objectField = array[1]; aget-object v2, v0, v4 sput-object v2, LMain;->objectField:Ljava/lang/Object; # objectField = array[2]; aget-object v2, v0, v5 sput-object v2, LMain;->objectField:Ljava/lang/Object; # objectField = array[3]; aget-object v2, v0, v6 sput-object v2, LMain;->objectField:Ljava/lang/Object; # long[] longArray = getLongArray(); invoke-static {}, LMain;->getLongArray()[J move-result-object v1 # longField = longArray[0]; aget-wide v2, v1, v3 sput-wide v2, LMain;->longField:J # longField = longArray[1]; aget-wide v2, v1, v4 sput-wide v2, LMain;->longField:J # longField = longArray[2]; aget-wide v2, v1, v5 sput-wide v2, LMain;->longField:J # longField = longArray[3]; aget-wide v2, v1, v6 sput-wide v2, LMain;->longField:J return-void .end method # static fields .field static doThrow:Z # boolean # direct methods .method static constructor ()V .registers 1 .prologue # doThrow = false const/4 v0, 0x0 sput-boolean v0, LSmaliTests;->doThrow:Z return-void .end method