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_final (before) 30 ## CHECK: Add 31 32 ## CHECK-START: int TestCase.testDeadEntry(int, int, int, int) dead_code_elimination_final (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_final (after) 38 ## CHECK-NOT: Add 39 40 ## CHECK-START: int TestCase.testDeadEntry(int, int, int, int) dead_code_elimination_final (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_final (before) 75 ## CHECK: Add 76 77 ## CHECK-START: int TestCase.testDeadExit(int, int, int, int) dead_code_elimination_final (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_final (after) 83 ## CHECK-NOT: Add 84 85 ## CHECK-START: int TestCase.testDeadExit(int, int, int, int) dead_code_elimination_final (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_final (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_final (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_final (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_final (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_final (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: <<Select:i\d+>> Select [<<Const0xf>>,<<Add>>,{{z\d+}}] 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 [<<Select>>,<<Const0x10>>,<<Const0x11>>] reg:3 is_catch_phi:true 222 223 ## CHECK-START: int TestCase.testCatchPhiInputs_DefinedInTryBlock(int, int, int, int) dead_code_elimination_final (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_final (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_final (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