1# Copyright (C) 2015 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 LTestCase; 16.super Ljava/lang/Object; 17 18.field public static sField:I 19 20.method private static $inline$False()Z 21 .registers 1 22 const/4 v0, 0x0 23 return v0 24.end method 25 26# Test a case when one entering TryBoundary is dead but the rest of the try 27# block remains live. 28 29## CHECK-START: int TestCase.testDeadEntry(int, int, int, int) dead_code_elimination$after_inlining (before) 30## CHECK: Add 31 32## CHECK-START: int TestCase.testDeadEntry(int, int, int, int) dead_code_elimination$after_inlining (before) 33## CHECK: TryBoundary kind:entry 34## CHECK: TryBoundary kind:entry 35## CHECK-NOT: TryBoundary kind:entry 36 37## CHECK-START: int TestCase.testDeadEntry(int, int, int, int) dead_code_elimination$after_inlining (after) 38## CHECK-NOT: Add 39 40## CHECK-START: int TestCase.testDeadEntry(int, int, int, int) dead_code_elimination$after_inlining (after) 41## CHECK: TryBoundary kind:entry 42## CHECK-NOT: TryBoundary kind:entry 43 44.method public static testDeadEntry(IIII)I 45 .registers 5 46 47 invoke-static {}, LTestCase;->$inline$False()Z 48 move-result v0 49 50 if-eqz v0, :else 51 52 add-int/2addr p0, p1 53 54 :try_start 55 div-int/2addr p0, p2 56 57 :else 58 div-int/2addr p0, p3 59 :try_end 60 .catchall {:try_start .. :try_end} :catch_all 61 62 :return 63 return p0 64 65 :catch_all 66 const/4 p0, -0x1 67 goto :return 68 69.end method 70 71# Test a case when one exiting TryBoundary is dead but the rest of the try 72# block remains live. 73 74## CHECK-START: int TestCase.testDeadExit(int, int, int, int) dead_code_elimination$after_inlining (before) 75## CHECK: Add 76 77## CHECK-START: int TestCase.testDeadExit(int, int, int, int) dead_code_elimination$after_inlining (before) 78## CHECK: TryBoundary kind:exit 79## CHECK: TryBoundary kind:exit 80## CHECK-NOT: TryBoundary kind:exit 81 82## CHECK-START: int TestCase.testDeadExit(int, int, int, int) dead_code_elimination$after_inlining (after) 83## CHECK-NOT: Add 84 85## CHECK-START: int TestCase.testDeadExit(int, int, int, int) dead_code_elimination$after_inlining (after) 86## CHECK: TryBoundary kind:exit 87## CHECK-NOT: TryBoundary kind:exit 88 89.method public static testDeadExit(IIII)I 90 .registers 5 91 92 invoke-static {}, LTestCase;->$inline$False()Z 93 move-result v0 94 95 :try_start 96 div-int/2addr p0, p2 97 98 if-nez v0, :else 99 100 div-int/2addr p0, p3 101 goto :return 102 :try_end 103 .catchall {:try_start .. :try_end} :catch_all 104 105 :else 106 add-int/2addr p0, p1 107 108 :return 109 return p0 110 111 :catch_all 112 const/4 p0, -0x1 113 goto :return 114 115.end method 116 117# Test that a catch block remains live and consistent if some of try blocks 118# throwing into it are removed. 119 120## CHECK-START: int TestCase.testOneTryBlockDead(int, int, int, int) dead_code_elimination$after_inlining (before) 121## CHECK: TryBoundary kind:entry 122## CHECK: TryBoundary kind:entry 123## CHECK-NOT: TryBoundary kind:entry 124 125## CHECK-START: int TestCase.testOneTryBlockDead(int, int, int, int) dead_code_elimination$after_inlining (before) 126## CHECK: TryBoundary kind:exit 127## CHECK: TryBoundary kind:exit 128## CHECK-NOT: TryBoundary kind:exit 129 130## CHECK-START: int TestCase.testOneTryBlockDead(int, int, int, int) dead_code_elimination$after_inlining (after) 131## CHECK: TryBoundary kind:entry 132## CHECK-NOT: TryBoundary kind:entry 133 134## CHECK-START: int TestCase.testOneTryBlockDead(int, int, int, int) dead_code_elimination$after_inlining (after) 135## CHECK: TryBoundary kind:exit 136## CHECK-NOT: TryBoundary kind:exit 137 138.method public static testOneTryBlockDead(IIII)I 139 .registers 5 140 141 invoke-static {}, LTestCase;->$inline$False()Z 142 move-result v0 143 144 :try_start_1 145 div-int/2addr p0, p2 146 :try_end_1 147 .catchall {:try_start_1 .. :try_end_1} :catch_all 148 149 if-eqz v0, :return 150 151 :try_start_2 152 div-int/2addr p0, p3 153 :try_end_2 154 .catchall {:try_start_2 .. :try_end_2} :catch_all 155 156 :return 157 return p0 158 159 :catch_all 160 const/4 p0, -0x1 161 goto :return 162 163.end method 164 165# Test that try block membership is recomputed. In this test case, the try entry 166# stored with the merge block gets deleted and SSAChecker would fail if it was 167# not replaced with the try entry from the live branch. 168 169.method public static testRecomputeTryMembership(IIII)I 170 .registers 5 171 172 invoke-static {}, LTestCase;->$inline$False()Z 173 move-result v0 174 175 if-eqz v0, :else 176 177 # Dead branch 178 :try_start 179 div-int/2addr p0, p1 180 goto :merge 181 182 # Live branch 183 :else 184 div-int/2addr p0, p2 185 186 # Merge block. Make complex so it does not get merged with the live branch. 187 :merge 188 div-int/2addr p0, p3 189 if-eqz p0, :else2 190 div-int/2addr p0, p3 191 :else2 192 :try_end 193 .catchall {:try_start .. :try_end} :catch_all 194 195 :return 196 return p0 197 198 :catch_all 199 const/4 p0, -0x1 200 goto :return 201 202.end method 203 204# Test that DCE removes catch phi uses of instructions defined in dead try blocks. 205 206## CHECK-START: int TestCase.testCatchPhiInputs_DefinedInTryBlock(int, int, int, int) dead_code_elimination$after_inlining (before) 207## CHECK-DAG: <<Arg0:i\d+>> ParameterValue 208## CHECK-DAG: <<Arg1:i\d+>> ParameterValue 209## CHECK-DAG: <<Const0xa:i\d+>> IntConstant 10 210## CHECK-DAG: <<Const0xb:i\d+>> IntConstant 11 211## CHECK-DAG: <<Const0xc:i\d+>> IntConstant 12 212## CHECK-DAG: <<Const0xd:i\d+>> IntConstant 13 213## CHECK-DAG: <<Const0xe:i\d+>> IntConstant 14 214## CHECK-DAG: <<Const0xf:i\d+>> IntConstant 15 215## CHECK-DAG: <<Const0x10:i\d+>> IntConstant 16 216## CHECK-DAG: <<Const0x11:i\d+>> IntConstant 17 217## CHECK-DAG: <<Add:i\d+>> Add [<<Arg0>>,<<Arg1>>] 218## CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Const0xf>>] reg:3 is_catch_phi:false 219## CHECK-DAG: Phi [<<Const0xa>>,<<Const0xb>>,<<Const0xd>>] reg:1 is_catch_phi:true 220## CHECK-DAG: Phi [<<Add>>,<<Const0xc>>,<<Const0xe>>] reg:2 is_catch_phi:true 221## CHECK-DAG: Phi [<<Phi>>,<<Const0x10>>,<<Const0x11>>] reg:3 is_catch_phi:true 222 223## CHECK-START: int TestCase.testCatchPhiInputs_DefinedInTryBlock(int, int, int, int) dead_code_elimination$after_inlining (after) 224## CHECK-DAG: <<Const0xb:i\d+>> IntConstant 11 225## CHECK-DAG: <<Const0xc:i\d+>> IntConstant 12 226## CHECK-DAG: <<Const0xd:i\d+>> IntConstant 13 227## CHECK-DAG: <<Const0xe:i\d+>> IntConstant 14 228## CHECK-DAG: <<Const0x10:i\d+>> IntConstant 16 229## CHECK-DAG: <<Const0x11:i\d+>> IntConstant 17 230## CHECK-DAG: Phi [<<Const0xb>>,<<Const0xd>>] reg:1 is_catch_phi:true 231## CHECK-DAG: Phi [<<Const0xc>>,<<Const0xe>>] reg:2 is_catch_phi:true 232## CHECK-DAG: Phi [<<Const0x10>>,<<Const0x11>>] reg:3 is_catch_phi:true 233 234.method public static testCatchPhiInputs_DefinedInTryBlock(IIII)I 235 .registers 8 236 237 invoke-static {}, LTestCase;->$inline$False()Z 238 move-result v0 239 240 if-eqz v0, :else 241 242 shr-int/2addr p2, p3 243 244 :try_start 245 const v1, 0xa # dead catch phi input, defined in entry block (HInstruction) 246 add-int v2, p0, p1 # dead catch phi input, defined in the dead block (HInstruction) 247 move v3, v2 248 if-eqz v3, :define_phi 249 const v3, 0xf 250 :define_phi 251 # v3 = Phi [Add, 0xf] # dead catch phi input, defined in the dead block (HPhi) 252 div-int/2addr p0, v2 253 254 :else 255 const v1, 0xb # live catch phi input 256 const v2, 0xc # live catch phi input 257 const v3, 0x10 # live catch phi input 258 div-int/2addr p0, p3 259 260 const v1, 0xd # live catch phi input 261 const v2, 0xe # live catch phi input 262 const v3, 0x11 # live catch phi input 263 div-int/2addr p0, p1 264 :try_end 265 .catchall {:try_start .. :try_end} :catch_all 266 267 :return 268 return p0 269 270 :catch_all 271 sub-int p0, v1, v2 # use catch phi values 272 sub-int p0, p0, v3 # use catch phi values 273 goto :return 274 275.end method 276 277# Test that DCE does not remove catch phi uses of instructions defined outside 278# dead try blocks. 279 280## CHECK-START: int TestCase.testCatchPhiInputs_DefinedOutsideTryBlock(int, int, int, int) dead_code_elimination$after_inlining (before) 281## CHECK-DAG: <<Const0xa:i\d+>> IntConstant 10 282## CHECK-DAG: <<Const0xb:i\d+>> IntConstant 11 283## CHECK-DAG: <<Const0xc:i\d+>> IntConstant 12 284## CHECK-DAG: <<Const0xd:i\d+>> IntConstant 13 285## CHECK-DAG: <<Const0xe:i\d+>> IntConstant 14 286## CHECK-DAG: <<Const0xf:i\d+>> IntConstant 15 287## CHECK-DAG: Phi [<<Const0xa>>,<<Const0xb>>,<<Const0xd>>] reg:1 is_catch_phi:true 288## CHECK-DAG: Phi [<<Const0xf>>,<<Const0xc>>,<<Const0xe>>] reg:2 is_catch_phi:true 289 290## CHECK-START: int TestCase.testCatchPhiInputs_DefinedOutsideTryBlock(int, int, int, int) dead_code_elimination$after_inlining (after) 291## CHECK-DAG: <<Const0xa:i\d+>> IntConstant 10 292## CHECK-DAG: <<Const0xb:i\d+>> IntConstant 11 293## CHECK-DAG: <<Const0xc:i\d+>> IntConstant 12 294## CHECK-DAG: <<Const0xd:i\d+>> IntConstant 13 295## CHECK-DAG: <<Const0xe:i\d+>> IntConstant 14 296## CHECK-DAG: <<Const0xf:i\d+>> IntConstant 15 297## CHECK-DAG: Phi [<<Const0xa>>,<<Const0xb>>,<<Const0xd>>] reg:1 is_catch_phi:true 298## CHECK-DAG: Phi [<<Const0xf>>,<<Const0xc>>,<<Const0xe>>] reg:2 is_catch_phi:true 299 300.method public static testCatchPhiInputs_DefinedOutsideTryBlock(IIII)I 301 .registers 7 302 303 invoke-static {}, LTestCase;->$inline$False()Z 304 move-result v0 305 306 if-eqz v0, :else 307 308 shr-int/2addr p2, p3 309 310 :try_start 311 const v1, 0xa # dead catch phi input, defined in entry block 312 const v2, 0xf # dead catch phi input, defined in entry block 313 div-int/2addr p0, v2 314 315 :else 316 const v1, 0xb # live catch phi input 317 const v2, 0xc # live catch phi input 318 div-int/2addr p0, p3 319 320 const v1, 0xd # live catch phi input 321 const v2, 0xe # live catch phi input 322 div-int/2addr p0, p1 323 :try_end 324 .catchall {:try_start .. :try_end} :catch_all 325 326 :return 327 return p0 328 329 :catch_all 330 sub-int p0, v1, v2 # use catch phi values 331 goto :return 332 333.end method 334