Home | History | Annotate | Download | only in smali
      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