blob: 710e849c45a9375e7d49f6b776cbe192abc1910a [file] [log] [blame]
# 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) ssa_builder (after)
## CHECK: name "B0"
## CHECK-NEXT: from_bci
## CHECK-NEXT: to_bci
## CHECK-NEXT: predecessors
## CHECK-NEXT: successors "<<BExtracted:B\d+>>"
## CHECK: name "<<BCatch:B\d+>>"
## CHECK-NEXT: from_bci
## CHECK-NEXT: to_bci
## CHECK-NEXT: predecessors
## CHECK-NEXT: successors "<<BExtracted>>"
## CHECK-NEXT: xhandlers
## CHECK-NEXT: flags "catch_block"
## CHECK-NOT: Add
## CHECK: name "<<BExtracted>>"
## CHECK-NEXT: from_bci
## CHECK-NEXT: to_bci
## CHECK-NEXT: predecessors "B0" "<<BCatch>>"
## CHECK-NOT: flags "catch_block"
## CHECK: Add
.method public static testSimplifyCatchBlock(III)I
.registers 4
: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) ssa_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) ssa_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) ssa_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) ssa_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) ssa_builder (before)
## CHECK: Mul
## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) ssa_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) ssa_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