1# Copyright (C) 2017 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15.class public LSmaliTests; 16.super Ljava/lang/Object; 17 18## CHECK-START: void SmaliTests.bar() load_store_elimination (after) 19## CHECK-DAG: <<Null:l\d+>> NullConstant 20## CHECK-DAG: <<BoundType:l\d+>> BoundType [<<Null>>] 21## CHECK-DAG: <<CheckL:l\d+>> NullCheck [<<BoundType>>] 22## CHECK-DAG: <<GetL0:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 23## CHECK-DAG: <<GetL1:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 24## CHECK-DAG: <<GetL2:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 25## CHECK-DAG: <<GetL3:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 26## CHECK-DAG: <<CheckJ:l\d+>> NullCheck [<<Null>>] 27## CHECK-DAG: <<GetJ0:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 28## CHECK-DAG: <<GetJ1:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 29## CHECK-DAG: <<GetJ2:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 30## CHECK-DAG: <<GetJ3:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 31.method public static bar()V 32 .registers 7 33 34 .prologue 35 const/4 v6, 0x3 36 const/4 v5, 0x2 37 const/4 v4, 0x1 38 const/4 v3, 0x0 39 40 # We create multiple accesses that will lead the bounds check 41 # elimination pass to add a HDeoptimize. Not having the bounds check helped 42 # the load store elimination think it could merge two ArrayGet with different 43 # types. 44 45 # String[] array = (String[])getNull(); 46 invoke-static {}, LMain;->getNull()Ljava/lang/Object; 47 move-result-object v0 48 check-cast v0, [Ljava/lang/String; 49 50 # objectField = array[0]; 51 aget-object v2, v0, v3 52 sput-object v2, LMain;->objectField:Ljava/lang/Object; 53 # objectField = array[1]; 54 aget-object v2, v0, v4 55 sput-object v2, LMain;->objectField:Ljava/lang/Object; 56 # objectField = array[2]; 57 aget-object v2, v0, v5 58 sput-object v2, LMain;->objectField:Ljava/lang/Object; 59 # objectField = array[3]; 60 aget-object v2, v0, v6 61 sput-object v2, LMain;->objectField:Ljava/lang/Object; 62 63 # long[] longArray = getLongArray(); 64 invoke-static {}, LMain;->getLongArray()[J 65 move-result-object v1 66 67 # longField = longArray[0]; 68 aget-wide v2, v1, v3 69 sput-wide v2, LMain;->longField:J 70 # longField = longArray[1]; 71 aget-wide v2, v1, v4 72 sput-wide v2, LMain;->longField:J 73 # longField = longArray[2]; 74 aget-wide v2, v1, v5 75 sput-wide v2, LMain;->longField:J 76 # longField = longArray[3]; 77 aget-wide v2, v1, v6 78 sput-wide v2, LMain;->longField:J 79 80 return-void 81.end method 82 83# This is indentical to bar() except that it has two check-casts 84# that DX tends to generate. 85 86## CHECK-START: void SmaliTests.bar2() load_store_elimination (after) 87## CHECK-DAG: <<Null:l\d+>> NullConstant 88## CHECK-DAG: <<BoundFirst:l\d+>> BoundType [<<Null>>] 89## CHECK-DAG: <<BoundType:l\d+>> BoundType [<<BoundFirst>>] 90## CHECK-DAG: <<CheckL:l\d+>> NullCheck [<<BoundType>>] 91## CHECK-DAG: <<GetL0:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 92## CHECK-DAG: <<GetL1:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 93## CHECK-DAG: <<GetL2:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 94## CHECK-DAG: <<GetL3:l\d+>> ArrayGet [<<CheckL>>,{{i\d+}}] 95## CHECK-DAG: <<CheckJ:l\d+>> NullCheck [<<Null>>] 96## CHECK-DAG: <<GetJ0:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 97## CHECK-DAG: <<GetJ1:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 98## CHECK-DAG: <<GetJ2:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 99## CHECK-DAG: <<GetJ3:j\d+>> ArrayGet [<<CheckJ>>,{{i\d+}}] 100.method public static bar2()V 101 .registers 7 102 103 .prologue 104 const/4 v6, 0x3 105 const/4 v5, 0x2 106 const/4 v4, 0x1 107 const/4 v3, 0x0 108 109 # We create multiple accesses that will lead the bounds check 110 # elimination pass to add a HDeoptimize. Not having the bounds check helped 111 # the load store elimination think it could merge two ArrayGet with different 112 # types. 113 114 # String[] array = (String[])getNull(); 115 invoke-static {}, LMain;->getNull()Ljava/lang/Object; 116 move-result-object v2 117 check-cast v2, [Ljava/lang/String; 118 119 move-object v0, v2 120 check-cast v0, [Ljava/lang/String; 121 122 # objectField = array[0]; 123 aget-object v2, v0, v3 124 sput-object v2, LMain;->objectField:Ljava/lang/Object; 125 # objectField = array[1]; 126 aget-object v2, v0, v4 127 sput-object v2, LMain;->objectField:Ljava/lang/Object; 128 # objectField = array[2]; 129 aget-object v2, v0, v5 130 sput-object v2, LMain;->objectField:Ljava/lang/Object; 131 # objectField = array[3]; 132 aget-object v2, v0, v6 133 sput-object v2, LMain;->objectField:Ljava/lang/Object; 134 135 # long[] longArray = getLongArray(); 136 invoke-static {}, LMain;->getLongArray()[J 137 move-result-object v1 138 139 # longField = longArray[0]; 140 aget-wide v2, v1, v3 141 sput-wide v2, LMain;->longField:J 142 # longField = longArray[1]; 143 aget-wide v2, v1, v4 144 sput-wide v2, LMain;->longField:J 145 # longField = longArray[2]; 146 aget-wide v2, v1, v5 147 sput-wide v2, LMain;->longField:J 148 # longField = longArray[3]; 149 aget-wide v2, v1, v6 150 sput-wide v2, LMain;->longField:J 151 152 return-void 153.end method 154 155# static fields 156.field static doThrow:Z # boolean 157 158# direct methods 159.method static constructor <clinit>()V 160 .registers 1 161 162 .prologue 163 # doThrow = false 164 const/4 v0, 0x0 165 sput-boolean v0, LSmaliTests;->doThrow:Z 166 return-void 167.end method 168