# 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 "<>" ## CHECK: name "<>" ## CHECK-NEXT: from_bci ## CHECK-NEXT: to_bci ## CHECK-NEXT: predecessors "B1" "<>" ## CHECK-NEXT: successors ## CHECK-NEXT: xhandlers ## CHECK-NOT: end_block ## CHECK: Add ## CHECK: name "<>" ## CHECK-NEXT: from_bci ## CHECK-NEXT: to_bci ## CHECK-NEXT: predecessors ## CHECK-NEXT: successors "<>" ## 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: <> ParameterValue ## CHECK-DAG: <> ParameterValue ## CHECK-DAG: <> ParameterValue ## CHECK-DAG: <> DivZeroCheck [<>] ## CHECK-DAG: <> Div [<>,<>] ## CHECK-DAG: <> DivZeroCheck [<>] ## CHECK-DAG: <> Div [<>,<>] ## CHECK-DAG: <> DivZeroCheck [<>] ## CHECK-DAG: <> Div [<>,<>] ## CHECK-DAG: <> Phi [<>,<>,<>] reg:0 is_catch_phi:true ## CHECK-DAG: <> Phi [<>,<>] reg:0 is_catch_phi:false ## CHECK-DAG: Return [<>] .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: <> ParameterValue ## CHECK-DAG: <> ParameterValue ## CHECK-DAG: <> IntConstant 5 ## CHECK-DAG: <> IntConstant 7 ## CHECK-DAG: <> Add [<>,<>] ## CHECK-DAG: <> DivZeroCheck [<>] ## CHECK-DAG: <> Div [<>,<>] ## CHECK-DAG: <> Phi [<>] reg:1 is_catch_phi:true ## CHECK-DAG: <> Add [<>,<>] ## CHECK-DAG: <> Phi [<>,<>] reg:0 is_catch_phi:false ## CHECK-DAG: Return [<>] .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: <> ParameterValue ## CHECK-DAG: <> ParameterValue ## CHECK-DAG: <> ParameterValue ## CHECK-DAG: <> Add [<>,<>] ## CHECK-DAG: <> Add [<>,<>] ## CHECK-DAG: Return [<>] ## 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