1*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2015 The Android Open Source Project 2*795d594fSAndroid Build Coastguard Worker# 3*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*795d594fSAndroid Build Coastguard Worker# 7*795d594fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*795d594fSAndroid Build Coastguard Worker# 9*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*795d594fSAndroid Build Coastguard Worker# limitations under the License. 14*795d594fSAndroid Build Coastguard Worker 15*795d594fSAndroid Build Coastguard Worker.class public LSsaBuilder; 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker.super Ljava/lang/Object; 18*795d594fSAndroid Build Coastguard Worker 19*795d594fSAndroid Build Coastguard Worker# Tests that catch blocks with both normal and exceptional predecessors are 20*795d594fSAndroid Build Coastguard Worker# split in two. 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker## CHECK-START: int SsaBuilder.testSimplifyCatchBlock(int, int, int) builder (after) 23*795d594fSAndroid Build Coastguard Worker 24*795d594fSAndroid Build Coastguard Worker## CHECK: name "B1" 25*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: from_bci 26*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: to_bci 27*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: predecessors 28*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: successors "<<BAdd:B\d+>>" 29*795d594fSAndroid Build Coastguard Worker 30*795d594fSAndroid Build Coastguard Worker## CHECK: name "<<BAdd>>" 31*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: from_bci 32*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: to_bci 33*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: predecessors "B1" "<<BCatch:B\d+>>" 34*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: successors 35*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: xhandlers 36*795d594fSAndroid Build Coastguard Worker## CHECK-NOT: end_block 37*795d594fSAndroid Build Coastguard Worker## CHECK: Add 38*795d594fSAndroid Build Coastguard Worker 39*795d594fSAndroid Build Coastguard Worker## CHECK: name "<<BCatch>>" 40*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: from_bci 41*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: to_bci 42*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: predecessors 43*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: successors "<<BAdd>>" 44*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: xhandlers 45*795d594fSAndroid Build Coastguard Worker## CHECK-NEXT: flags "catch_block" 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker.method public static testSimplifyCatchBlock(III)I 48*795d594fSAndroid Build Coastguard Worker .registers 4 49*795d594fSAndroid Build Coastguard Worker # Avoid entry block be a pre header, which leads to 50*795d594fSAndroid Build Coastguard Worker # the cfg simplifier to add a synthesized block. 51*795d594fSAndroid Build Coastguard Worker goto :catch_all 52*795d594fSAndroid Build Coastguard Worker 53*795d594fSAndroid Build Coastguard Worker :catch_all 54*795d594fSAndroid Build Coastguard Worker add-int/2addr p0, p1 55*795d594fSAndroid Build Coastguard Worker 56*795d594fSAndroid Build Coastguard Worker :try_start 57*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p2 58*795d594fSAndroid Build Coastguard Worker :try_end 59*795d594fSAndroid Build Coastguard Worker .catchall {:try_start .. :try_end} :catch_all 60*795d594fSAndroid Build Coastguard Worker 61*795d594fSAndroid Build Coastguard Worker return p0 62*795d594fSAndroid Build Coastguard Worker.end method 63*795d594fSAndroid Build Coastguard Worker 64*795d594fSAndroid Build Coastguard Worker# Should be rejected because :catch_all is a loop header. 65*795d594fSAndroid Build Coastguard Worker 66*795d594fSAndroid Build Coastguard Worker## CHECK-START: int SsaBuilder.testCatchLoopHeader(int, int, int) builder (after, bad_state) 67*795d594fSAndroid Build Coastguard Worker 68*795d594fSAndroid Build Coastguard Worker.method public static testCatchLoopHeader(III)I 69*795d594fSAndroid Build Coastguard Worker .registers 4 70*795d594fSAndroid Build Coastguard Worker 71*795d594fSAndroid Build Coastguard Worker :try_start_1 72*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p1 73*795d594fSAndroid Build Coastguard Worker return p0 74*795d594fSAndroid Build Coastguard Worker :try_end_1 75*795d594fSAndroid Build Coastguard Worker .catchall {:try_start_1 .. :try_end_1} :catch_all 76*795d594fSAndroid Build Coastguard Worker 77*795d594fSAndroid Build Coastguard Worker :catch_all 78*795d594fSAndroid Build Coastguard Worker :try_start_2 79*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p2 80*795d594fSAndroid Build Coastguard Worker return p0 81*795d594fSAndroid Build Coastguard Worker :try_end_2 82*795d594fSAndroid Build Coastguard Worker .catchall {:try_start_2 .. :try_end_2} :catch_all 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker.end method 85*795d594fSAndroid Build Coastguard Worker 86*795d594fSAndroid Build Coastguard Worker# Tests creation of catch Phis. 87*795d594fSAndroid Build Coastguard Worker 88*795d594fSAndroid Build Coastguard Worker## CHECK-START: int SsaBuilder.testPhiCreation(int, int, int) builder (after) 89*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P0:i\d+>> ParameterValue 90*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P1:i\d+>> ParameterValue 91*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P2:i\d+>> ParameterValue 92*795d594fSAndroid Build Coastguard Worker 93*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<DZC1:i\d+>> DivZeroCheck [<<P1>>] 94*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Div1:i\d+>> Div [<<P0>>,<<DZC1>>] 95*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<DZC2:i\d+>> DivZeroCheck [<<P1>>] 96*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Div2:i\d+>> Div [<<Div1>>,<<DZC2>>] 97*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<DZC3:i\d+>> DivZeroCheck [<<P1>>] 98*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Div3:i\d+>> Div [<<Div2>>,<<DZC3>>] 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Phi1:i\d+>> Phi [<<P0>>,<<P1>>,<<P2>>] reg:0 is_catch_phi:true 101*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Phi2:i\d+>> Phi [<<Div3>>,<<Phi1>>] reg:0 is_catch_phi:false 102*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Return [<<Phi2>>] 103*795d594fSAndroid Build Coastguard Worker 104*795d594fSAndroid Build Coastguard Worker.method public static testPhiCreation(III)I 105*795d594fSAndroid Build Coastguard Worker .registers 4 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker :try_start 108*795d594fSAndroid Build Coastguard Worker move v0, p0 109*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p1 110*795d594fSAndroid Build Coastguard Worker 111*795d594fSAndroid Build Coastguard Worker move v0, p1 112*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p1 113*795d594fSAndroid Build Coastguard Worker 114*795d594fSAndroid Build Coastguard Worker move v0, p2 115*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p1 116*795d594fSAndroid Build Coastguard Worker 117*795d594fSAndroid Build Coastguard Worker move v0, p0 118*795d594fSAndroid Build Coastguard Worker :try_end 119*795d594fSAndroid Build Coastguard Worker .catchall {:try_start .. :try_end} :catch_all 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker :return 122*795d594fSAndroid Build Coastguard Worker return v0 123*795d594fSAndroid Build Coastguard Worker 124*795d594fSAndroid Build Coastguard Worker :catch_all 125*795d594fSAndroid Build Coastguard Worker goto :return 126*795d594fSAndroid Build Coastguard Worker.end method 127*795d594fSAndroid Build Coastguard Worker 128*795d594fSAndroid Build Coastguard Worker# Tests that phi elimination does not remove catch phis where the value does 129*795d594fSAndroid Build Coastguard Worker# not dominate the phi. 130*795d594fSAndroid Build Coastguard Worker 131*795d594fSAndroid Build Coastguard Worker## CHECK-START: int SsaBuilder.testPhiElimination_Domination(int, int) builder (after) 132*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P0:i\d+>> ParameterValue 133*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P1:i\d+>> ParameterValue 134*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Cst5:i\d+>> IntConstant 5 135*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Cst7:i\d+>> IntConstant 7 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Add1:i\d+>> Add [<<Cst7>>,<<Cst7>>] 138*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<DZC:i\d+>> DivZeroCheck [<<P1>>] 139*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Div:i\d+>> Div [<<P0>>,<<DZC>>] 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Phi1:i\d+>> Phi [<<Add1>>] reg:1 is_catch_phi:true 142*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Add2:i\d+>> Add [<<Cst5>>,<<Phi1>>] 143*795d594fSAndroid Build Coastguard Worker 144*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Phi2:i\d+>> Phi [<<Cst5>>,<<Add2>>] reg:0 is_catch_phi:false 145*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Return [<<Phi2>>] 146*795d594fSAndroid Build Coastguard Worker 147*795d594fSAndroid Build Coastguard Worker.method public static testPhiElimination_Domination(II)I 148*795d594fSAndroid Build Coastguard Worker .registers 4 149*795d594fSAndroid Build Coastguard Worker 150*795d594fSAndroid Build Coastguard Worker :try_start 151*795d594fSAndroid Build Coastguard Worker # The constant in entry block will dominate the vreg 0 catch phi. 152*795d594fSAndroid Build Coastguard Worker const v0, 5 153*795d594fSAndroid Build Coastguard Worker 154*795d594fSAndroid Build Coastguard Worker # Insert addition so that the value of vreg 1 does not dominate the phi. 155*795d594fSAndroid Build Coastguard Worker const v1, 7 156*795d594fSAndroid Build Coastguard Worker add-int/2addr v1, v1 157*795d594fSAndroid Build Coastguard Worker 158*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p1 159*795d594fSAndroid Build Coastguard Worker :try_end 160*795d594fSAndroid Build Coastguard Worker .catchall {:try_start .. :try_end} :catch_all 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker :return 163*795d594fSAndroid Build Coastguard Worker return v0 164*795d594fSAndroid Build Coastguard Worker 165*795d594fSAndroid Build Coastguard Worker :catch_all 166*795d594fSAndroid Build Coastguard Worker add-int/2addr v0, v1 167*795d594fSAndroid Build Coastguard Worker goto :return 168*795d594fSAndroid Build Coastguard Worker.end method 169*795d594fSAndroid Build Coastguard Worker 170*795d594fSAndroid Build Coastguard Worker# Tests that phi elimination loops until no more phis can be removed. 171*795d594fSAndroid Build Coastguard Worker 172*795d594fSAndroid Build Coastguard Worker## CHECK-START: int SsaBuilder.testPhiElimination_Dependencies(int, int, int) builder (after) 173*795d594fSAndroid Build Coastguard Worker## CHECK-NOT: Phi 174*795d594fSAndroid Build Coastguard Worker 175*795d594fSAndroid Build Coastguard Worker.method public static testPhiElimination_Dependencies(III)I 176*795d594fSAndroid Build Coastguard Worker .registers 4 177*795d594fSAndroid Build Coastguard Worker 178*795d594fSAndroid Build Coastguard Worker # This constant reaches Return via the normal control-flow path and both 179*795d594fSAndroid Build Coastguard Worker # exceptional paths. Since v0 is never changed, there should be no phis. 180*795d594fSAndroid Build Coastguard Worker const v0, 5 181*795d594fSAndroid Build Coastguard Worker 182*795d594fSAndroid Build Coastguard Worker :try_start 183*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p1 184*795d594fSAndroid Build Coastguard Worker div-int/2addr p0, p2 185*795d594fSAndroid Build Coastguard Worker :try_end 186*795d594fSAndroid Build Coastguard Worker .catch Ljava/lang/ArithmeticException; {:try_start .. :try_end} :catch_arith 187*795d594fSAndroid Build Coastguard Worker .catchall {:try_start .. :try_end} :catch_all 188*795d594fSAndroid Build Coastguard Worker 189*795d594fSAndroid Build Coastguard Worker :return 190*795d594fSAndroid Build Coastguard Worker # Phi [v0, CatchPhi1, CatchPhi2] 191*795d594fSAndroid Build Coastguard Worker return v0 192*795d594fSAndroid Build Coastguard Worker 193*795d594fSAndroid Build Coastguard Worker :catch_arith 194*795d594fSAndroid Build Coastguard Worker # CatchPhi1 [v0, v0] 195*795d594fSAndroid Build Coastguard Worker goto :return 196*795d594fSAndroid Build Coastguard Worker 197*795d594fSAndroid Build Coastguard Worker :catch_all 198*795d594fSAndroid Build Coastguard Worker # CatchPhi2 [v0, v0] 199*795d594fSAndroid Build Coastguard Worker goto :return 200*795d594fSAndroid Build Coastguard Worker.end method 201*795d594fSAndroid Build Coastguard Worker 202*795d594fSAndroid Build Coastguard Worker# Tests that dead catch blocks are removed. 203*795d594fSAndroid Build Coastguard Worker 204*795d594fSAndroid Build Coastguard Worker## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) builder (after) 205*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P0:i\d+>> ParameterValue 206*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P1:i\d+>> ParameterValue 207*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<P2:i\d+>> ParameterValue 208*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Add1:i\d+>> Add [<<P0>>,<<P1>>] 209*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<P2>>] 210*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Return [<<Add2>>] 211*795d594fSAndroid Build Coastguard Worker 212*795d594fSAndroid Build Coastguard Worker## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) builder (after) 213*795d594fSAndroid Build Coastguard Worker## CHECK-NOT: flags "catch_block" 214*795d594fSAndroid Build Coastguard Worker## CHECK-NOT: Mul 215*795d594fSAndroid Build Coastguard Worker 216*795d594fSAndroid Build Coastguard Worker.method public static testDeadCatchBlock(III)I 217*795d594fSAndroid Build Coastguard Worker .registers 4 218*795d594fSAndroid Build Coastguard Worker 219*795d594fSAndroid Build Coastguard Worker :try_start 220*795d594fSAndroid Build Coastguard Worker add-int/2addr p0, p1 221*795d594fSAndroid Build Coastguard Worker add-int/2addr p0, p2 222*795d594fSAndroid Build Coastguard Worker move v0, p0 223*795d594fSAndroid Build Coastguard Worker :try_end 224*795d594fSAndroid Build Coastguard Worker .catchall {:try_start .. :try_end} :catch_all 225*795d594fSAndroid Build Coastguard Worker 226*795d594fSAndroid Build Coastguard Worker :return 227*795d594fSAndroid Build Coastguard Worker return v0 228*795d594fSAndroid Build Coastguard Worker 229*795d594fSAndroid Build Coastguard Worker :catch_all 230*795d594fSAndroid Build Coastguard Worker mul-int/2addr v1, v1 231*795d594fSAndroid Build Coastguard Worker goto :return 232*795d594fSAndroid Build Coastguard Worker.end method 233