| # Copyright (C) 2015 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 LSsaBuilder; |
| |
| .super Ljava/lang/Object; |
| |
| # Tests that catch blocks with both normal and exceptional predecessors are |
| # split in two. |
| |
| ## CHECK-START: int SsaBuilder.testSimplifyCatchBlock(int, int, int) builder (after) |
| |
| ## CHECK: name "B1" |
| ## CHECK-NEXT: from_bci |
| ## CHECK-NEXT: to_bci |
| ## CHECK-NEXT: predecessors |
| ## CHECK-NEXT: successors "<<BAdd:B\d+>>" |
| |
| ## CHECK: name "<<BAdd>>" |
| ## CHECK-NEXT: from_bci |
| ## CHECK-NEXT: to_bci |
| ## CHECK-NEXT: predecessors "B1" "<<BCatch:B\d+>>" |
| ## CHECK-NEXT: successors |
| ## CHECK-NEXT: xhandlers |
| ## CHECK-NOT: end_block |
| ## CHECK: Add |
| |
| ## CHECK: name "<<BCatch>>" |
| ## CHECK-NEXT: from_bci |
| ## CHECK-NEXT: to_bci |
| ## CHECK-NEXT: predecessors |
| ## CHECK-NEXT: successors "<<BAdd>>" |
| ## CHECK-NEXT: xhandlers |
| ## CHECK-NEXT: flags "catch_block" |
| |
| .method public static testSimplifyCatchBlock(III)I |
| .registers 4 |
| # Avoid entry block be a pre header, which leads to |
| # the cfg simplifier to add a synthesized block. |
| goto :catch_all |
| |
| :catch_all |
| add-int/2addr p0, p1 |
| |
| :try_start |
| div-int/2addr p0, p2 |
| :try_end |
| .catchall {:try_start .. :try_end} :catch_all |
| |
| return p0 |
| .end method |
| |
| # Should be rejected because :catch_all is a loop header. |
| |
| ## CHECK-START: int SsaBuilder.testCatchLoopHeader(int, int, int) builder (after, bad_state) |
| |
| .method public static testCatchLoopHeader(III)I |
| .registers 4 |
| |
| :try_start_1 |
| div-int/2addr p0, p1 |
| return p0 |
| :try_end_1 |
| .catchall {:try_start_1 .. :try_end_1} :catch_all |
| |
| :catch_all |
| :try_start_2 |
| div-int/2addr p0, p2 |
| return p0 |
| :try_end_2 |
| .catchall {:try_start_2 .. :try_end_2} :catch_all |
| |
| .end method |
| |
| # Tests creation of catch Phis. |
| |
| ## CHECK-START: int SsaBuilder.testPhiCreation(int, int, int) builder (after) |
| ## CHECK-DAG: <<P0:i\d+>> ParameterValue |
| ## CHECK-DAG: <<P1:i\d+>> ParameterValue |
| ## CHECK-DAG: <<P2:i\d+>> ParameterValue |
| |
| ## CHECK-DAG: <<DZC1:i\d+>> DivZeroCheck [<<P1>>] |
| ## CHECK-DAG: <<Div1:i\d+>> Div [<<P0>>,<<DZC1>>] |
| ## CHECK-DAG: <<DZC2:i\d+>> DivZeroCheck [<<P1>>] |
| ## CHECK-DAG: <<Div2:i\d+>> Div [<<Div1>>,<<DZC2>>] |
| ## CHECK-DAG: <<DZC3:i\d+>> DivZeroCheck [<<P1>>] |
| ## CHECK-DAG: <<Div3:i\d+>> Div [<<Div2>>,<<DZC3>>] |
| |
| ## CHECK-DAG: <<Phi1:i\d+>> Phi [<<P0>>,<<P1>>,<<P2>>] reg:0 is_catch_phi:true |
| ## CHECK-DAG: <<Phi2:i\d+>> Phi [<<Div3>>,<<Phi1>>] reg:0 is_catch_phi:false |
| ## CHECK-DAG: Return [<<Phi2>>] |
| |
| .method public static testPhiCreation(III)I |
| .registers 4 |
| |
| :try_start |
| move v0, p0 |
| div-int/2addr p0, p1 |
| |
| move v0, p1 |
| div-int/2addr p0, p1 |
| |
| move v0, p2 |
| div-int/2addr p0, p1 |
| |
| move v0, p0 |
| :try_end |
| .catchall {:try_start .. :try_end} :catch_all |
| |
| :return |
| return v0 |
| |
| :catch_all |
| goto :return |
| .end method |
| |
| # Tests that phi elimination does not remove catch phis where the value does |
| # not dominate the phi. |
| |
| ## CHECK-START: int SsaBuilder.testPhiElimination_Domination(int, int) builder (after) |
| ## CHECK-DAG: <<P0:i\d+>> ParameterValue |
| ## CHECK-DAG: <<P1:i\d+>> ParameterValue |
| ## CHECK-DAG: <<Cst5:i\d+>> IntConstant 5 |
| ## CHECK-DAG: <<Cst7:i\d+>> IntConstant 7 |
| |
| ## CHECK-DAG: <<Add1:i\d+>> Add [<<Cst7>>,<<Cst7>>] |
| ## CHECK-DAG: <<DZC:i\d+>> DivZeroCheck [<<P1>>] |
| ## CHECK-DAG: <<Div:i\d+>> Div [<<P0>>,<<DZC>>] |
| |
| ## CHECK-DAG: <<Phi1:i\d+>> Phi [<<Add1>>] reg:1 is_catch_phi:true |
| ## CHECK-DAG: <<Add2:i\d+>> Add [<<Cst5>>,<<Phi1>>] |
| |
| ## CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cst5>>,<<Add2>>] reg:0 is_catch_phi:false |
| ## CHECK-DAG: Return [<<Phi2>>] |
| |
| .method public static testPhiElimination_Domination(II)I |
| .registers 4 |
| |
| :try_start |
| # The constant in entry block will dominate the vreg 0 catch phi. |
| const v0, 5 |
| |
| # Insert addition so that the value of vreg 1 does not dominate the phi. |
| const v1, 7 |
| add-int/2addr v1, v1 |
| |
| div-int/2addr p0, p1 |
| :try_end |
| .catchall {:try_start .. :try_end} :catch_all |
| |
| :return |
| return v0 |
| |
| :catch_all |
| add-int/2addr v0, v1 |
| goto :return |
| .end method |
| |
| # Tests that phi elimination loops until no more phis can be removed. |
| |
| ## CHECK-START: int SsaBuilder.testPhiElimination_Dependencies(int, int, int) builder (after) |
| ## CHECK-NOT: Phi |
| |
| .method public static testPhiElimination_Dependencies(III)I |
| .registers 4 |
| |
| # This constant reaches Return via the normal control-flow path and both |
| # exceptional paths. Since v0 is never changed, there should be no phis. |
| const v0, 5 |
| |
| :try_start |
| div-int/2addr p0, p1 |
| div-int/2addr p0, p2 |
| :try_end |
| .catch Ljava/lang/ArithmeticException; {:try_start .. :try_end} :catch_arith |
| .catchall {:try_start .. :try_end} :catch_all |
| |
| :return |
| # Phi [v0, CatchPhi1, CatchPhi2] |
| return v0 |
| |
| :catch_arith |
| # CatchPhi1 [v0, v0] |
| goto :return |
| |
| :catch_all |
| # CatchPhi2 [v0, v0] |
| goto :return |
| .end method |
| |
| # Tests that dead catch blocks are removed. |
| |
| ## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) builder (after) |
| ## CHECK-DAG: <<P0:i\d+>> ParameterValue |
| ## CHECK-DAG: <<P1:i\d+>> ParameterValue |
| ## CHECK-DAG: <<P2:i\d+>> ParameterValue |
| ## CHECK-DAG: <<Add1:i\d+>> Add [<<P0>>,<<P1>>] |
| ## CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<P2>>] |
| ## CHECK-DAG: Return [<<Add2>>] |
| |
| ## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) builder (after) |
| ## CHECK-NOT: flags "catch_block" |
| ## CHECK-NOT: Mul |
| |
| .method public static testDeadCatchBlock(III)I |
| .registers 4 |
| |
| :try_start |
| add-int/2addr p0, p1 |
| add-int/2addr p0, p2 |
| move v0, p0 |
| :try_end |
| .catchall {:try_start .. :try_end} :catch_all |
| |
| :return |
| return v0 |
| |
| :catch_all |
| mul-int/2addr v1, v1 |
| goto :return |
| .end method |