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