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