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 LBuilder;
16
17.super Ljava/lang/Object;
18
19# Basic test case with two try blocks and three catch handlers, one of which
20# is shared by the two tries.
21
22## CHECK-START: int Builder.testMultipleTryCatch(int, int, int) builder (after)
23
24## CHECK:      name             "B0"
25## CHECK:      successors       "<<BEnterTry1:B\d+>>"
26## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
27## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
28## CHECK-DAG:  <<Minus3:i\d+>>  IntConstant -3
29
30## CHECK:  name             "<<BTry1:B\d+>>"
31## CHECK:  predecessors     "<<BEnterTry1>>"
32## CHECK:  successors       "<<BExitTry1:B\d+>>"
33## CHECK:  DivZeroCheck
34
35## CHECK:  name             "<<BAdd:B\d+>>"
36## CHECK:  predecessors     "<<BExitTry1>>"
37## CHECK:  successors       "<<BEnterTry2:B\d+>>"
38## CHECK:  Add
39
40## CHECK:  name             "<<BTry2:B\d+>>"
41## CHECK:  predecessors     "<<BEnterTry2>>"
42## CHECK:  successors       "<<BExitTry2:B\d+>>"
43## CHECK:  DivZeroCheck
44## CHECK:  <<Div:i\d+>> Div
45
46## CHECK:  name             "<<BAfterTry2:B\d+>>"
47## CHECK:  predecessors     "<<BExitTry2>>"
48## CHECK:  successors       "<<BReturn:B\d+>>"
49## CHECK:  Goto
50
51## CHECK:  name             "<<BReturn>>"
52## CHECK:  predecessors     "<<BAfterTry2>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>" "<<BCatch3:B\d+>>"
53## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>,<<Minus3>>]
54## CHECK:  Return
55
56## CHECK:  name             "<<BCatch1>>"
57## CHECK:  predecessors     "<<BEnterTry1>>" "<<BExitTry1>>"
58## CHECK:  successors       "<<BReturn>>"
59## CHECK:  flags            "catch_block"
60## CHECK:  Goto
61
62## CHECK:  name             "<<BCatch2>>"
63## CHECK:  predecessors     "<<BEnterTry2>>" "<<BExitTry2>>"
64## CHECK:  successors       "<<BReturn>>"
65## CHECK:  flags            "catch_block"
66## CHECK:  Goto
67
68## CHECK:  name             "<<BCatch3>>"
69## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
70## CHECK:  successors       "<<BReturn>>"
71## CHECK:  flags            "catch_block"
72## CHECK:  Goto
73
74## CHECK:  name             "<<BEnterTry1>>"
75## CHECK:  predecessors     "B0"
76## CHECK:  successors       "<<BTry1>>"
77## CHECK:  xhandlers        "<<BCatch1>>" "<<BCatch3>>"
78## CHECK:  TryBoundary      kind:entry
79
80## CHECK:  name             "<<BEnterTry2>>"
81## CHECK:  predecessors     "<<BAdd>>"
82## CHECK:  successors       "<<BTry2>>"
83## CHECK:  xhandlers        "<<BCatch2>>" "<<BCatch3>>"
84## CHECK:  TryBoundary      kind:entry
85
86## CHECK:  name             "<<BExitTry1>>"
87## CHECK:  predecessors     "<<BTry1>>"
88## CHECK:  successors       "<<BAdd>>"
89## CHECK:  xhandlers        "<<BCatch1>>" "<<BCatch3>>"
90## CHECK:  TryBoundary      kind:exit
91
92## CHECK:  name             "<<BExitTry2>>"
93## CHECK:  predecessors     "<<BTry2>>"
94## CHECK:  successors       "<<BAfterTry2>>"
95## CHECK:  xhandlers        "<<BCatch2>>" "<<BCatch3>>"
96## CHECK:  TryBoundary      kind:exit
97
98.method public static testMultipleTryCatch(III)I
99    .registers 3
100
101    :try_start_1
102    div-int/2addr p0, p1
103    :try_end_1
104    .catch Ljava/lang/ArithmeticException; {:try_start_1 .. :try_end_1} :catch_arith
105    .catchall {:try_start_1 .. :try_end_1} :catch_other
106
107    add-int/2addr p0, p0
108
109    :try_start_2
110    div-int/2addr p0, p2
111    :try_end_2
112    .catch Ljava/lang/OutOfMemoryError; {:try_start_2 .. :try_end_2} :catch_mem
113    .catchall {:try_start_2 .. :try_end_2} :catch_other
114
115    nop
116
117    :return
118    return p0
119
120    :catch_arith
121    const/4 p0, -0x1
122    goto :return
123
124    :catch_mem
125    const/4 p0, -0x2
126    goto :return
127
128    :catch_other
129    const/4 p0, -0x3
130    goto :return
131.end method
132
133# Tests try-entry block when there are multiple entry points into the try block.
134
135## CHECK-START: int Builder.testMultipleEntries(int, int, int, int) builder (after)
136
137## CHECK:  name             "B0"
138## CHECK:  successors       "<<BIf:B\d+>>"
139## CHECK:  <<Minus1:i\d+>>  IntConstant -1
140
141## CHECK:  name             "<<BIf>>"
142## CHECK:  predecessors     "B0"
143## CHECK:  successors       "<<BSplit1:B\d+>>" "<<BThen:B\d+>>"
144## CHECK:  If
145
146## CHECK:  name             "<<BThen>>"
147## CHECK:  predecessors     "<<BIf>>"
148## CHECK:  successors       "<<BEnterTry1:B\d+>>"
149## CHECK:  Div
150
151## CHECK:  name             "<<BTry1:B\d+>>"
152## CHECK:  predecessors     "<<BEnterTry1>>"
153## CHECK:  successors       "<<BExitTry1:B\d+>>"
154## CHECK:  Div
155
156## CHECK:  name             "<<BTry2:B\d+>>"
157## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
158## CHECK:  successors       "<<BExitTry2:B\d+>>"
159## CHECK:  Div
160
161## CHECK:  name             "<<BReturn:B\d+>>"
162## CHECK:  predecessors     "<<BSplit3:B\d+>>" "<<BCatch:B\d+>>"
163## CHECK:  Return
164
165## CHECK:  name             "<<BCatch>>"
166## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
167## CHECK:  successors       "<<BReturn>>"
168## CHECK:  flags            "catch_block"
169## CHECK:  Goto
170
171## CHECK:  name             "<<BEnterTry1>>"
172## CHECK:  predecessors     "<<BThen>>"
173## CHECK:  successors       "<<BTry1>>"
174## CHECK:  xhandlers        "<<BCatch>>"
175## CHECK:  TryBoundary      kind:entry
176
177## CHECK:  name             "<<BEnterTry2>>"
178## CHECK:  predecessors     "<<BSplit1>>" "<<BSplit2:B\d+>>"
179## CHECK:  successors       "<<BTry2>>"
180## CHECK:  xhandlers        "<<BCatch>>"
181## CHECK:  TryBoundary      kind:entry
182
183## CHECK:  name             "<<BExitTry1>>"
184## CHECK:  predecessors     "<<BTry1>>"
185## CHECK:  successors       "<<BSplit2>>"
186## CHECK:  xhandlers        "<<BCatch>>"
187## CHECK:  TryBoundary      kind:exit
188
189## CHECK:  name             "<<BExitTry2>>"
190## CHECK:  predecessors     "<<BTry2>>"
191## CHECK:  successors       "<<BSplit3>>"
192## CHECK:  xhandlers        "<<BCatch>>"
193## CHECK:  TryBoundary      kind:exit
194
195## CHECK:  name             "<<BSplit1>>"
196## CHECK:  predecessors     "<<BIf>>"
197## CHECK:  successors       "<<BEnterTry2>>"
198## CHECK:  Goto
199
200## CHECK:  name             "<<BSplit2>>"
201## CHECK:  predecessors     "<<BExitTry1>>"
202## CHECK:  successors       "<<BEnterTry2>>"
203## CHECK:  Goto
204
205## CHECK:  name             "<<BSplit3>>"
206## CHECK:  predecessors     "<<BExitTry2>>"
207## CHECK:  successors       "<<BReturn>>"
208## CHECK:  Goto
209
210.method public static testMultipleEntries(IIII)I
211    .registers 4
212
213    if-eqz p2, :else
214
215    div-int/2addr p0, p1
216
217    :try_start
218    div-int/2addr p0, p2
219
220    :else
221    div-int/2addr p0, p3
222    :try_end
223    .catchall {:try_start .. :try_end} :catch_all
224
225    :return
226    return p0
227
228    :catch_all
229    const/4 p0, -0x1
230    goto :return
231
232.end method
233
234# Test that multiple try-exit blocks are generated if (normal) control flow can
235# jump out of the try block at multiple points.
236
237## CHECK-START: int Builder.testMultipleExits(int, int) builder (after)
238
239## CHECK:      name             "B0"
240## CHECK:      successors       "<<BEnterTry:B\d+>>"
241## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
242## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
243
244## CHECK:  name             "<<BTry:B\d+>>"
245## CHECK:  predecessors     "<<BEnterTry>>"
246## CHECK:  successors       "<<BExitTry1:B\d+>>" "<<BExitTry2:B\d+>>"
247## CHECK:  <<Div:i\d+>> Div
248## CHECK:  If
249
250## CHECK:  name             "<<BReturn:B\d+>>"
251## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BThen:B\d+>>" "<<BCatch:B\d+>>"
252## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
253## CHECK:  Return
254
255## CHECK:  name             "<<BThen>>"
256## CHECK:  predecessors     "<<BExitTry1>>"
257## CHECK:  successors       "<<BReturn>>"
258## CHECK:  Goto
259
260## CHECK:  name             "<<BCatch>>"
261## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry1>>" "<<BExitTry2>>"
262## CHECK:  successors       "<<BReturn>>"
263## CHECK:  flags            "catch_block"
264## CHECK:  Goto
265
266## CHECK:  name             "<<BEnterTry>>"
267## CHECK:  predecessors     "B0"
268## CHECK:  successors       "<<BTry>>"
269## CHECK:  xhandlers        "<<BCatch>>"
270## CHECK:  TryBoundary      kind:entry
271
272## CHECK:  name             "<<BExitTry1>>"
273## CHECK:  predecessors     "<<BTry>>"
274## CHECK:  successors       "<<BThen>>"
275## CHECK:  xhandlers        "<<BCatch>>"
276## CHECK:  TryBoundary      kind:exit
277
278## CHECK:  name             "<<BExitTry2>>"
279## CHECK:  predecessors     "<<BTry>>"
280## CHECK:  successors       "<<BSplit>>"
281## CHECK:  xhandlers        "<<BCatch>>"
282## CHECK:  TryBoundary      kind:exit
283
284## CHECK:  name             "<<BSplit>>"
285## CHECK:  predecessors     "<<BExitTry2>>"
286## CHECK:  successors       "<<BReturn>>"
287## CHECK:  Goto
288
289.method public static testMultipleExits(II)I
290    .registers 2
291
292    :try_start
293    div-int/2addr p0, p1
294    if-eqz p0, :then
295    :try_end
296    .catchall {:try_start .. :try_end} :catch_all
297
298    :return
299    return p0
300
301    :then
302    const/4 p0, -0x1
303    goto :return
304
305    :catch_all
306    const/4 p0, -0x2
307    goto :return
308.end method
309
310# Test that only one TryBoundary is inserted when an edge connects two different
311# try ranges.
312
313## CHECK-START: int Builder.testSharedBoundary(int, int, int) builder (after)
314
315## CHECK:      name             "B0"
316## CHECK:      successors       "<<BEnter1:B\d+>>"
317## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
318## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
319
320## CHECK:  name             "<<BTry1:B\d+>>"
321## CHECK:  predecessors     "<<BEnter1>>"
322## CHECK:  successors       "<<BExit1:B\d+>>"
323## CHECK:  Div
324
325## CHECK:  name             "<<BTry2:B\d+>>"
326## CHECK:  predecessors     "<<BEnter2:B\d+>>"
327## CHECK:  successors       "<<BExit2:B\d+>>"
328## CHECK:  <<Div:i\d+>> Div
329## CHECK:  Goto
330
331## CHECK:  name             "<<BReturn:B\d+>>"
332## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
333## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
334## CHECK:  Return
335
336## CHECK:  name             "<<BCatch1>>"
337## CHECK:  predecessors     "<<BEnter1>>" "<<BExit1>>"
338## CHECK:  successors       "<<BReturn>>"
339## CHECK:  flags            "catch_block"
340## CHECK:  Goto
341
342## CHECK:  name             "<<BCatch2>>"
343## CHECK:  predecessors     "<<BEnter2>>" "<<BExit2>>"
344## CHECK:  successors       "<<BReturn>>"
345## CHECK:  flags            "catch_block"
346## CHECK:  Goto
347
348## CHECK:  name             "<<BEnter1>>"
349## CHECK:  predecessors     "B0"
350## CHECK:  successors       "<<BTry1>>"
351## CHECK:  xhandlers        "<<BCatch1>>"
352## CHECK:  TryBoundary      kind:entry
353
354## CHECK:  name             "<<BEnter2>>"
355## CHECK:  predecessors     "<<BExit1>>"
356## CHECK:  successors       "<<BTry2>>"
357## CHECK:  xhandlers        "<<BCatch2>>"
358## CHECK:  TryBoundary      kind:entry
359
360## CHECK:  name             "<<BExit1>>"
361## CHECK:  predecessors     "<<BTry1>>"
362## CHECK:  successors       "<<BEnter2>>"
363## CHECK:  xhandlers        "<<BCatch1>>"
364## CHECK:  TryBoundary      kind:exit
365
366## CHECK:  name             "<<BExit2>>"
367## CHECK:  predecessors     "<<BTry2>>"
368## CHECK:  successors       "<<BSplit>>"
369## CHECK:  xhandlers        "<<BCatch2>>"
370## CHECK:  TryBoundary      kind:exit
371
372## CHECK:  name             "<<BSplit>>"
373## CHECK:  predecessors     "<<BExit2>>"
374## CHECK:  successors       "<<BReturn>>"
375## CHECK:  Goto
376
377.method public static testSharedBoundary(III)I
378    .registers 3
379
380    :try_start_1
381    div-int/2addr p0, p1
382    :try_end_1
383    .catchall {:try_start_1 .. :try_end_1} :catch_all_1
384
385    :try_start_2
386    div-int/2addr p0, p2
387    :try_end_2
388    .catchall {:try_start_2 .. :try_end_2} :catch_all_2
389
390    :return
391    return p0
392
393    :catch_all_1
394    const/4 p0, -0x1
395    goto :return
396
397    :catch_all_2
398    const/4 p0, -0x2
399    goto :return
400.end method
401
402# Same as previous test, only the blocks are processed in the opposite order.
403
404## CHECK-START: int Builder.testSharedBoundary_Reverse(int, int, int) builder (after)
405
406## CHECK:      name             "B0"
407## CHECK:      successors       "<<BGoto:B\d+>>"
408## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
409## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
410
411## CHECK:  name             "<<BGoto>>"
412## CHECK:  successors       "<<BEnter2:B\d+>>"
413## CHECK:  Goto
414
415## CHECK:  name             "<<BTry1:B\d+>>"
416## CHECK:  predecessors     "<<BEnter1:B\d+>>"
417## CHECK:  successors       "<<BExit1:B\d+>>"
418## CHECK:  <<Div:i\d+>> Div
419## CHECK:  Goto
420
421## CHECK:  name             "<<BTry2:B\d+>>"
422## CHECK:  predecessors     "<<BEnter2>>"
423## CHECK:  successors       "<<BExit2:B\d+>>"
424## CHECK:  Div
425## CHECK:  Goto
426
427## CHECK:  name             "<<BReturn:B\d+>>"
428## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
429## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
430## CHECK:  Return
431
432## CHECK:  name             "<<BCatch1>>"
433## CHECK:  predecessors     "<<BEnter1>>" "<<BExit1>>"
434## CHECK:  successors       "<<BReturn>>"
435## CHECK:  flags            "catch_block"
436## CHECK:  Goto
437
438## CHECK:  name             "<<BCatch2>>"
439## CHECK:  predecessors     "<<BEnter2>>" "<<BExit2>>"
440## CHECK:  successors       "<<BReturn>>"
441## CHECK:  flags            "catch_block"
442## CHECK:  Goto
443
444## CHECK:  name             "<<BEnter1>>"
445## CHECK:  predecessors     "<<BExit2>>"
446## CHECK:  successors       "<<BTry1>>"
447## CHECK:  xhandlers        "<<BCatch1>>"
448## CHECK:  TryBoundary      kind:entry
449
450## CHECK:  name             "<<BEnter2>>"
451## CHECK:  predecessors     "<<BGoto>>"
452## CHECK:  successors       "<<BTry2>>"
453## CHECK:  xhandlers        "<<BCatch2>>"
454## CHECK:  TryBoundary      kind:entry
455
456## CHECK:  name             "<<BExit1>>"
457## CHECK:  predecessors     "<<BTry1>>"
458## CHECK:  successors       "<<BSplit>>"
459## CHECK:  xhandlers        "<<BCatch1>>"
460## CHECK:  TryBoundary      kind:exit
461
462## CHECK:  name             "<<BExit2>>"
463## CHECK:  predecessors     "<<BTry2>>"
464## CHECK:  successors       "<<BEnter1>>"
465## CHECK:  xhandlers        "<<BCatch2>>"
466## CHECK:  TryBoundary      kind:exit
467
468## CHECK:  name             "<<BSplit>>"
469## CHECK:  predecessors     "<<BExit1>>"
470## CHECK:  successors       "<<BReturn>>"
471## CHECK:  Goto
472
473.method public static testSharedBoundary_Reverse(III)I
474    .registers 3
475
476    goto :try_start_2
477
478    :try_start_1
479    div-int/2addr p0, p1
480    goto :return
481    :try_end_1
482    .catchall {:try_start_1 .. :try_end_1} :catch_all_1
483
484    :try_start_2
485    div-int/2addr p0, p2
486    goto :try_start_1
487    :try_end_2
488    .catchall {:try_start_2 .. :try_end_2} :catch_all_2
489
490    :return
491    return p0
492
493    :catch_all_1
494    const/4 p0, -0x1
495    goto :return
496
497    :catch_all_2
498    const/4 p0, -0x2
499    goto :return
500.end method
501
502# Test that nested tries are split into non-overlapping blocks and TryBoundary
503# blocks are correctly created between them.
504
505## CHECK-START: int Builder.testNestedTry(int, int, int, int) builder (after)
506
507## CHECK:      name             "B0"
508## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
509## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
510
511## CHECK:  name             "<<BTry1:B\d+>>"
512## CHECK:  predecessors     "<<BEnter1:B\d+>>"
513## CHECK:  successors       "<<BExit1:B\d+>>"
514## CHECK:  Div
515
516## CHECK:  name             "<<BTry2:B\d+>>"
517## CHECK:  predecessors     "<<BEnter2:B\d+>>"
518## CHECK:  successors       "<<BExit2:B\d+>>"
519## CHECK:  Div
520## CHECK:  Goto
521
522## CHECK:  name             "<<BTry3:B\d+>>"
523## CHECK:  predecessors     "<<BEnter3:B\d+>>"
524## CHECK:  successors       "<<BExit3:B\d+>>"
525## CHECK:  <<Div:i\d+>> Div
526## CHECK:  Goto
527
528## CHECK:  name             "<<BReturn:B\d+>>"
529## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatchArith:B\d+>>" "<<BCatchAll:B\d+>>"
530## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
531## CHECK:  Return
532
533## CHECK:  name             "<<BCatchArith>>"
534## CHECK:  predecessors     "<<BEnter2>>" "<<BExit2>>"
535## CHECK:  successors       "<<BReturn>>"
536## CHECK:  flags            "catch_block"
537## CHECK:  Goto
538
539## CHECK:  name             "<<BCatchAll>>"
540## CHECK:  predecessors     "<<BEnter1>>" "<<BEnter2>>" "<<BEnter3>>" "<<BExit1>>" "<<BExit2>>" "<<BExit3>>"
541## CHECK:  successors       "<<BReturn>>"
542## CHECK:  flags            "catch_block"
543## CHECK:  Goto
544
545## CHECK:  name             "<<BEnter1>>"
546## CHECK:  predecessors     "B0"
547## CHECK:  successors       "<<BTry1>>"
548## CHECK:  xhandlers        "<<BCatchAll>>"
549## CHECK:  TryBoundary      kind:entry
550
551## CHECK:  name             "<<BEnter2>>"
552## CHECK:  predecessors     "<<BExit1>>"
553## CHECK:  successors       "<<BTry2>>"
554## CHECK:  xhandlers        "<<BCatchArith>>" "<<BCatchAll>>"
555## CHECK:  TryBoundary      kind:entry
556
557## CHECK:  name             "<<BEnter3>>"
558## CHECK:  predecessors     "<<BExit2>>"
559## CHECK:  successors       "<<BTry3>>"
560## CHECK:  xhandlers        "<<BCatchAll>>"
561## CHECK:  TryBoundary      kind:entry
562
563## CHECK:  name             "<<BExit1>>"
564## CHECK:  predecessors     "<<BTry1>>"
565## CHECK:  successors       "<<BEnter2>>"
566## CHECK:  xhandlers        "<<BCatchAll>>"
567## CHECK:  TryBoundary      kind:exit
568
569## CHECK:  name             "<<BExit2>>"
570## CHECK:  predecessors     "<<BTry2>>"
571## CHECK:  successors       "<<BEnter3>>"
572## CHECK:  xhandlers        "<<BCatchArith>>" "<<BCatchAll>>"
573## CHECK:  TryBoundary      kind:exit
574
575## CHECK:  name             "<<BExit3>>"
576## CHECK:  predecessors     "<<BTry3>>"
577## CHECK:  successors       "<<BSplit>>"
578## CHECK:  xhandlers        "<<BCatchAll>>"
579## CHECK:  TryBoundary      kind:exit
580
581## CHECK:  name             "<<BSplit>>"
582## CHECK:  predecessors     "<<BExit3>>"
583## CHECK:  successors       "<<BReturn>>"
584## CHECK:  Goto
585
586.method public static testNestedTry(IIII)I
587    .registers 4
588
589    :try_start_1
590    div-int/2addr p0, p1
591
592    :try_start_2
593    div-int/2addr p0, p2
594    :try_end_2
595    .catch Ljava/lang/ArithmeticException; {:try_start_2 .. :try_end_2} :catch_arith
596
597    div-int/2addr p0, p3
598    :try_end_1
599    .catchall {:try_start_1 .. :try_end_1} :catch_all
600
601    :return
602    return p0
603
604    :catch_arith
605    const/4 p0, -0x1
606    goto :return
607
608    :catch_all
609    const/4 p0, -0x2
610    goto :return
611.end method
612
613# Test control flow that enters a try block, leaves it and returns again.
614
615## CHECK-START: int Builder.testIncontinuousTry(int, int, int, int) builder (after)
616
617## CHECK:  name             "B0"
618## CHECK:  <<Minus1:i\d+>>  IntConstant -1
619
620## CHECK:  name             "<<BTry1:B\d+>>"
621## CHECK:  predecessors     "<<BEnterTry1:B\d+>>"
622## CHECK:  successors       "<<BExitTry1:B\d+>>"
623## CHECK:  Div
624## CHECK:  Goto
625
626## CHECK:  name             "<<BTry2:B\d+>>"
627## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
628## CHECK:  successors       "<<BExitTry2:B\d+>>"
629## CHECK:  <<Div:i\d+>> Div
630## CHECK:  Goto
631
632## CHECK:  name             "<<BReturn:B\d+>>"
633## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch:B\d+>>"
634## CHECK:  Phi [<<Div>>,<<Minus1>>]
635## CHECK:  Return
636
637## CHECK:  name             "<<BOutside:B\d+>>"
638## CHECK:  predecessors     "<<BExitTry1>>"
639## CHECK:  successors       "<<BEnterTry2>>"
640## CHECK:  Div
641
642## CHECK:  name             "<<BCatch>>"
643## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
644## CHECK:  successors       "<<BReturn>>"
645## CHECK:  flags            "catch_block"
646## CHECK:  Goto
647
648## CHECK:  name             "<<BEnterTry1>>"
649## CHECK:  predecessors     "B0"
650## CHECK:  successors       "<<BTry1>>"
651## CHECK:  xhandlers        "<<BCatch>>"
652## CHECK:  TryBoundary      kind:entry
653
654## CHECK:  name             "<<BEnterTry2>>"
655## CHECK:  predecessors     "<<BOutside>>"
656## CHECK:  successors       "<<BTry2>>"
657## CHECK:  xhandlers        "<<BCatch>>"
658## CHECK:  TryBoundary      kind:entry
659
660## CHECK:  name             "<<BExitTry1>>"
661## CHECK:  predecessors     "<<BTry1>>"
662## CHECK:  successors       "<<BOutside>>"
663## CHECK:  xhandlers        "<<BCatch>>"
664## CHECK:  TryBoundary      kind:exit
665
666## CHECK:  name             "<<BExitTry2>>"
667## CHECK:  predecessors     "<<BTry2>>"
668## CHECK:  successors       "<<BSplit>>"
669## CHECK:  xhandlers        "<<BCatch>>"
670## CHECK:  TryBoundary      kind:exit
671
672## CHECK:  name             "<<BSplit>>"
673## CHECK:  predecessors     "<<BExitTry2>>"
674## CHECK:  successors       "<<BReturn>>"
675## CHECK:  Goto
676
677.method public static testIncontinuousTry(IIII)I
678    .registers 4
679
680    :try_start
681    div-int/2addr p0, p1
682    goto :outside
683
684    :inside
685    div-int/2addr p0, p3
686    :try_end
687    .catchall {:try_start .. :try_end} :catch_all
688
689    :return
690    return p0
691
692    :outside
693    div-int/2addr p0, p2
694    goto :inside
695
696    :catch_all
697    const/4 p0, -0x1
698    goto :return
699.end method
700
701## CHECK-START: int Builder.testSwitchTryEnter(int, int, int, int) builder (after)
702
703## CHECK:  name             "B0"
704## CHECK:  successors       "<<BPSwitch0:B\d+>>"
705
706## CHECK:  name             "<<BPSwitch0>>"
707## CHECK:  predecessors     "B0"
708## CHECK:  successors       "<<BSplit1:B\d+>>" "<<BPSwitch1:B\d+>>"
709## CHECK:  If
710
711## CHECK:  name             "<<BPSwitch1>>"
712## CHECK:  predecessors     "<<BPSwitch0>>"
713## CHECK:  successors       "<<BSplit2:B\d+>>" "<<BEnterTry1:B\d+>>"
714## CHECK:  If
715
716## CHECK:  name             "<<BTry1:B\d+>>"
717## CHECK:  predecessors     "<<BEnterTry1>>"
718## CHECK:  successors       "<<BExitTry1:B\d+>>"
719## CHECK:  Div
720
721## CHECK:  name             "<<BTry2:B\d+>>"
722## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
723## CHECK:  successors       "<<BExitTry2:B\d+>>"
724## CHECK:  Div
725
726## CHECK:  name             "<<BOutside:B\d+>>"
727## CHECK:  predecessors     "<<BSplit2>>" "<<BSplit4:B\d+>>"
728## CHECK:  successors       "<<BReturn:B\d+>>"
729## CHECK:  Div
730
731## CHECK:  name             "<<BReturn>>"
732## CHECK:  predecessors     "<<BOutside>>" "<<BCatch:B\d+>>"
733## CHECK:  successors       "<<BExit:B\d+>>"
734## CHECK:  Return
735
736## CHECK:  name             "<<BExit>>"
737## CHECK:  Exit
738
739## CHECK:  name             "<<BCatch>>"
740## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
741## CHECK:  successors       "<<BReturn>>"
742## CHECK:  flags            "catch_block"
743## CHECK:  Goto
744
745## CHECK:  name             "<<BEnterTry1>>"
746## CHECK:  predecessors     "<<BPSwitch1>>"
747## CHECK:  successors       "<<BTry1>>"
748## CHECK:  xhandlers        "<<BCatch>>"
749## CHECK:  TryBoundary      kind:entry
750
751## CHECK:  name             "<<BEnterTry2>>"
752## CHECK:  predecessors     "<<BSplit1>>" "<<BSplit3:B\d+>>"
753## CHECK:  successors       "<<BTry2>>"
754## CHECK:  xhandlers        "<<BCatch>>"
755## CHECK:  TryBoundary      kind:entry
756
757## CHECK:  name             "<<BExitTry1>>"
758## CHECK:  predecessors     "<<BTry1>>"
759## CHECK:  successors       "<<BSplit3>>"
760## CHECK:  xhandlers        "<<BCatch>>"
761## CHECK:  TryBoundary      kind:exit
762
763## CHECK:  name             "<<BExitTry2>>"
764## CHECK:  predecessors     "<<BTry2>>"
765## CHECK:  successors       "<<BSplit4>>"
766## CHECK:  xhandlers        "<<BCatch>>"
767## CHECK:  TryBoundary      kind:exit
768
769## CHECK:  name             "<<BSplit1>>"
770## CHECK:  predecessors     "<<BPSwitch0>>"
771## CHECK:  successors       "<<BEnterTry2>>"
772## CHECK:  Goto
773
774## CHECK:  name             "<<BSplit2>>"
775## CHECK:  predecessors     "<<BPSwitch1>>"
776## CHECK:  successors       "<<BOutside>>"
777## CHECK:  Goto
778
779## CHECK:  name             "<<BSplit3>>"
780## CHECK:  predecessors     "<<BExitTry1>>"
781## CHECK:  successors       "<<BEnterTry2>>"
782## CHECK:  Goto
783
784## CHECK:  name             "<<BSplit4>>"
785## CHECK:  predecessors     "<<BExitTry2>>"
786## CHECK:  successors       "<<BOutside>>"
787## CHECK:  Goto
788
789.method public static testSwitchTryEnter(IIII)I
790    .registers 4
791
792    packed-switch p0, :pswitch_data
793
794    :try_start
795    div-int/2addr p0, p1
796
797    :pswitch1
798    div-int/2addr p0, p2
799    goto :pswitch2
800
801    :pswitch_data
802    .packed-switch 0x0
803        :pswitch1
804        :pswitch2
805    .end packed-switch
806    :try_end
807    .catchall {:try_start .. :try_end} :catch_all
808
809    :pswitch2
810    div-int/2addr p0, p3
811
812    :catch_all
813    return p0
814.end method
815
816## CHECK-START: int Builder.testSwitchTryExit(int, int, int, int) builder (after)
817
818## CHECK:  name             "B0"
819## CHECK:  successors       "<<BEnterTry1:B\d+>>"
820
821## CHECK:  name             "<<BPSwitch0:B\d+>>"
822## CHECK:  predecessors     "<<BEnterTry1>>"
823## CHECK:  successors       "<<BSplit1:B\d+>>" "<<BExitTry1:B\d+>>"
824## CHECK:  If
825
826## CHECK:  name             "<<BPSwitch1:B\d+>>"
827## CHECK:  predecessors     "<<BExitTry1>>"
828## CHECK:  successors       "<<BSplit2:B\d+>>" "<<BEnterTry2:B\d+>>"
829## CHECK:  If
830
831## CHECK:  name             "<<BTry1:B\d+>>"
832## CHECK:  predecessors     "<<BEnterTry2>>"
833## CHECK:  successors       "<<BTry2:B\d+>>"
834## CHECK:  Div
835
836## CHECK:  name             "<<BTry2>>"
837## CHECK:  predecessors     "<<BSplit1>>" "<<BTry1>>"
838## CHECK:  successors       "<<BExitTry2:B\d+>>"
839## CHECK:  Div
840
841## CHECK:  name             "<<BOutside:B\d+>>"
842## CHECK:  predecessors     "<<BSplit2>>" "<<BSplit3:B\d+>>"
843## CHECK:  successors       "<<BReturn:B\d+>>"
844## CHECK:  Div
845
846## CHECK:  name             "<<BReturn>>"
847## CHECK:  predecessors     "<<BOutside>>" "<<BCatch:B\d+>>"
848## CHECK:  successors       "<<BExit:B\d+>>"
849## CHECK:  Return
850
851## CHECK:  name             "<<BExit>>"
852## CHECK:  Exit
853
854## CHECK:  name             "<<BCatch>>"
855## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
856## CHECK:  successors       "<<BReturn>>"
857## CHECK:  flags            "catch_block"
858## CHECK:  Goto
859
860## CHECK:  name             "<<BEnterTry1>>"
861## CHECK:  predecessors     "B0"
862## CHECK:  successors       "<<BPSwitch0>>"
863## CHECK:  xhandlers        "<<BCatch>>"
864## CHECK:  TryBoundary      kind:entry
865
866## CHECK:  name             "<<BEnterTry2>>"
867## CHECK:  predecessors     "<<BPSwitch1>>"
868## CHECK:  successors       "<<BTry1>>"
869## CHECK:  xhandlers        "<<BCatch>>"
870## CHECK:  TryBoundary      kind:entry
871
872## CHECK:  name             "<<BExitTry1>>"
873## CHECK:  predecessors     "<<BPSwitch0>>"
874## CHECK:  successors       "<<BPSwitch1>>"
875## CHECK:  xhandlers        "<<BCatch>>"
876## CHECK:  TryBoundary      kind:exit
877
878## CHECK:  name             "<<BExitTry2>>"
879## CHECK:  predecessors     "<<BTry2>>"
880## CHECK:  successors       "<<BSplit3>>"
881## CHECK:  xhandlers        "<<BCatch>>"
882## CHECK:  TryBoundary      kind:exit
883
884## CHECK:  name             "<<BSplit1>>"
885## CHECK:  predecessors     "<<BPSwitch0>>"
886## CHECK:  successors       "<<BTry2>>"
887## CHECK:  Goto
888
889## CHECK:  name             "<<BSplit2>>"
890## CHECK:  predecessors     "<<BPSwitch1>>"
891## CHECK:  successors       "<<BOutside>>"
892## CHECK:  Goto
893
894## CHECK:  name             "<<BSplit3>>"
895## CHECK:  predecessors     "<<BExitTry2>>"
896## CHECK:  successors       "<<BOutside>>"
897## CHECK:  Goto
898
899.method public static testSwitchTryExit(IIII)I
900    .registers 4
901
902    :try_start
903    div-int/2addr p0, p1
904    packed-switch p0, :pswitch_data
905
906    div-int/2addr p0, p1
907
908    :pswitch1
909    div-int/2addr p0, p2
910    :try_end
911    .catchall {:try_start .. :try_end} :catch_all
912
913    :pswitch2
914    div-int/2addr p0, p3
915
916    :catch_all
917    return p0
918
919    :pswitch_data
920    .packed-switch 0x0
921        :pswitch1
922        :pswitch2
923    .end packed-switch
924.end method
925
926# Test that a TryBoundary is inserted between a Throw instruction and the exit
927# block when covered by a try range.
928
929## CHECK-START: int Builder.testThrow(java.lang.Exception) builder (after)
930
931## CHECK:  name             "B0"
932## CHECK:  successors       "<<BEnterTry:B\d+>>"
933## CHECK:  <<Minus1:i\d+>>  IntConstant -1
934
935## CHECK:  name             "<<BTry:B\d+>>"
936## CHECK:  predecessors     "<<BEnterTry>>"
937## CHECK:  successors       "<<BExitTry:B\d+>>"
938## CHECK:  Throw
939
940## CHECK:  name             "<<BCatch:B\d+>>"
941## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry>>"
942## CHECK:  successors       "<<BExit:B\d+>>"
943## CHECK:  flags            "catch_block"
944## CHECK:  Return [<<Minus1>>]
945
946## CHECK:  name             "<<BExit>>"
947## CHECK:  predecessors     "<<BExitTry>>" "<<BCatch>>"
948## CHECK:  Exit
949
950## CHECK:  name             "<<BEnterTry>>"
951## CHECK:  predecessors     "B0"
952## CHECK:  successors       "<<BTry>>"
953## CHECK:  xhandlers        "<<BCatch>>"
954## CHECK:  TryBoundary      kind:entry
955
956## CHECK:  name             "<<BExitTry>>"
957## CHECK:  predecessors     "<<BTry>>"
958## CHECK:  successors       "<<BExit>>"
959## CHECK:  xhandlers        "<<BCatch>>"
960## CHECK:  TryBoundary      kind:exit
961
962.method public static testThrow(Ljava/lang/Exception;)I
963    .registers 2
964
965    :try_start
966    throw p0
967    :try_end
968    .catchall {:try_start .. :try_end} :catch_all
969
970    :catch_all
971    const/4 v0, -0x1
972    return v0
973.end method
974
975# Test graph with a throw/catch loop.
976
977## CHECK-START: int Builder.testCatchLoop(int, int, int) builder (after)
978
979## CHECK:  name             "B0"
980## CHECK:  successors       "<<BSplit:B\d+>>"
981
982## CHECK:  name             "<<BTry:B\d+>>"
983## CHECK:  predecessors     "<<BEnterTry:B\d+>>"
984## CHECK:  successors       "<<BExitTry:B\d+>>"
985## CHECK:  Div
986
987## CHECK:  name             "<<BReturn:B\d+>>"
988## CHECK:  predecessors     "<<BExitTry>>"
989## CHECK:  successors       "<<BExit:B\d+>>"
990## CHECK:  Return
991
992## CHECK:  name             "<<BExit>>"
993## CHECK:  predecessors     "<<BReturn>>"
994## CHECK:  Exit
995
996## CHECK:  name             "<<BCatch:B\d+>>"
997## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry>>"
998## CHECK:  successors       "<<BEnterTry>>"
999## CHECK:  flags            "catch_block"
1000## CHECK:  Goto
1001
1002## CHECK:  name             "<<BEnterTry>>"
1003## CHECK:  predecessors     "<<BSplit>>" "<<BCatch>>"
1004## CHECK:  successors       "<<BTry>>"
1005## CHECK:  xhandlers        "<<BCatch>>"
1006## CHECK:  TryBoundary      kind:entry
1007
1008## CHECK:  name             "<<BExitTry>>"
1009## CHECK:  predecessors     "<<BTry>>"
1010## CHECK:  successors       "<<BReturn>>"
1011## CHECK:  xhandlers        "<<BCatch>>"
1012## CHECK:  TryBoundary      kind:exit
1013
1014## CHECK:  name             "<<BSplit>>"
1015## CHECK:  predecessors     "B0"
1016## CHECK:  successors       "<<BEnterTry>>"
1017## CHECK:  Goto
1018
1019.method public static testCatchLoop(III)I
1020    .registers 4
1021
1022    :try_start
1023    :catch_all
1024    div-int/2addr p0, p2
1025    :try_end
1026    .catchall {:try_start .. :try_end} :catch_all
1027
1028    :return
1029    return p0
1030.end method
1031
1032# Test that handler edges are not split. In this scenario, the catch block is
1033# only the handler of the try block.
1034
1035## CHECK-START: int Builder.testHandlerEdge1(int, int, int) builder (after)
1036
1037## CHECK:  name             "B0"
1038## CHECK:  successors       "<<BEnterTry1:B\d+>>"
1039
1040## CHECK:  name             "<<BTry1:B\d+>>"
1041## CHECK:  predecessors     "<<BEnterTry1>>"
1042## CHECK:  successors       "<<BExitTry1:B\d+>>"
1043## CHECK:  Div
1044
1045## CHECK:  name             "<<BTry2:B\d+>>"
1046## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
1047## CHECK:  successors       "<<BExitTry2:B\d+>>"
1048## CHECK:  Div
1049
1050## CHECK:  name             "<<BReturn:B\d+>>"
1051## CHECK:  predecessors     "<<BExitTry2>>"
1052## CHECK:  successors       "<<BExit:B\d+>>"
1053## CHECK:  Return
1054
1055## CHECK:  name             "<<BExit>>"
1056## CHECK:  predecessors     "<<BReturn>>"
1057## CHECK:  Exit
1058
1059## CHECK:  name             "<<BCatch:B\d+>>"
1060## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
1061## CHECK:  successors       "<<BEnterTry2>>"
1062## CHECK:  flags            "catch_block"
1063## CHECK:  Goto
1064
1065## CHECK:  name             "<<BEnterTry1>>"
1066## CHECK:  predecessors     "B0"
1067## CHECK:  successors       "<<BTry1>>"
1068## CHECK:  xhandlers        "<<BCatch>>"
1069## CHECK:  TryBoundary      kind:entry
1070
1071## CHECK:  name             "<<BEnterTry2>>"
1072## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch>>"
1073## CHECK:  successors       "<<BTry2>>"
1074## CHECK:  xhandlers        "<<BCatch>>"
1075## CHECK:  TryBoundary      kind:entry
1076
1077## CHECK:  name             "<<BExitTry1>>"
1078## CHECK:  predecessors     "<<BTry1>>"
1079## CHECK:  successors       "<<BSplit>>"
1080## CHECK:  xhandlers        "<<BCatch>>"
1081## CHECK:  TryBoundary      kind:exit
1082
1083## CHECK:  name             "<<BExitTry2>>"
1084## CHECK:  predecessors     "<<BTry2>>"
1085## CHECK:  successors       "<<BReturn>>"
1086## CHECK:  xhandlers        "<<BCatch>>"
1087## CHECK:  TryBoundary      kind:exit
1088
1089## CHECK:  name             "<<BSplit>>"
1090## CHECK:  predecessors     "<<BExitTry1>>"
1091## CHECK:  successors       "<<BEnterTry2>>"
1092## CHECK:  Goto
1093
1094.method public static testHandlerEdge1(III)I
1095    .registers 4
1096
1097    :try_start
1098    div-int/2addr p0, p1
1099
1100    :catch_all
1101    div-int/2addr p0, p2
1102    :try_end
1103    .catchall {:try_start .. :try_end} :catch_all
1104
1105    return p0
1106.end method
1107
1108# Test that handler edges are not split. In this scenario, the catch block is
1109# the handler and also the successor of the try block.
1110
1111## CHECK-START: int Builder.testHandlerEdge2(int, int, int) builder (after)
1112
1113## CHECK:  name             "B0"
1114## CHECK:  successors       "<<BSplit1:B\d+>>"
1115
1116## CHECK:  name             "<<BTry1:B\d+>>"
1117## CHECK:  predecessors     "<<BEnterTry1:B\d+>>"
1118## CHECK:  successors       "<<BExitTry1:B\d+>>"
1119## CHECK:  Div
1120
1121## CHECK:  name             "<<BTry2:B\d+>>"
1122## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
1123## CHECK:  successors       "<<BExitTry2:B\d+>>"
1124## CHECK:  Div
1125
1126## CHECK:  name             "<<BReturn:B\d+>>"
1127## CHECK:  predecessors     "<<BExitTry2>>"
1128## CHECK:  successors       "<<BExit:B\d+>>"
1129## CHECK:  Return
1130
1131## CHECK:  name             "<<BExit>>"
1132## CHECK:  Exit
1133
1134## CHECK:  name             "<<BCatch2:B\d+>>"
1135## CHECK:  predecessors     "<<BEnterTry1>>" "<<BExitTry1>>"
1136## CHECK:  successors       "<<BEnterTry2>>"
1137## CHECK:  flags            "catch_block"
1138
1139## CHECK:  name             "<<BCatch1:B\d+>>"
1140## CHECK:  predecessors     "<<BEnterTry2>>" "<<BExitTry2>>"
1141## CHECK:  successors       "<<BEnterTry1>>"
1142## CHECK:  flags            "catch_block"
1143
1144## CHECK:  name             "<<BEnterTry1>>"
1145## CHECK:  predecessors     "<<BSplit1>>" "<<BCatch1>>"
1146## CHECK:  successors       "<<BTry1>>"
1147## CHECK:  xhandlers        "<<BCatch2>>"
1148## CHECK:  TryBoundary      kind:entry
1149
1150## CHECK:  name             "<<BEnterTry2>>"
1151## CHECK:  predecessors     "<<BSplit2:B\d+>>" "<<BCatch2>>"
1152## CHECK:  successors       "<<BTry2>>"
1153## CHECK:  xhandlers        "<<BCatch1>>"
1154## CHECK:  TryBoundary      kind:entry
1155
1156## CHECK:  name             "<<BExitTry1>>"
1157## CHECK:  predecessors     "<<BTry1>>"
1158## CHECK:  successors       "<<BSplit2>>"
1159## CHECK:  xhandlers        "<<BCatch2>>"
1160## CHECK:  TryBoundary      kind:exit
1161
1162## CHECK:  name             "<<BExitTry2>>"
1163## CHECK:  predecessors     "<<BTry2>>"
1164## CHECK:  successors       "<<BReturn>>"
1165## CHECK:  xhandlers        "<<BCatch1>>"
1166## CHECK:  TryBoundary      kind:exit
1167
1168## CHECK:  name             "<<BSplit1>>"
1169## CHECK:  predecessors     "B0"
1170## CHECK:  successors       "<<BEnterTry1>>"
1171## CHECK:  Goto
1172
1173## CHECK:  name             "<<BSplit2>>"
1174## CHECK:  predecessors     "<<BExitTry1>>"
1175## CHECK:  successors       "<<BEnterTry2>>"
1176## CHECK:  Goto
1177
1178.method public static testHandlerEdge2(III)I
1179    .registers 4
1180
1181    :try_start_1
1182    :catch_all_1
1183    div-int/2addr p0, p1
1184    :try_end_1
1185    .catchall {:try_start_1 .. :try_end_1} :catch_all_2
1186
1187    :try_start_2
1188    :catch_all_2
1189    div-int/2addr p0, p2
1190    :try_end_2
1191    .catchall {:try_start_2 .. :try_end_2} :catch_all_1
1192
1193    return p0
1194.end method
1195
1196# Test graph with try/catch inside a loop.
1197
1198## CHECK-START: int Builder.testTryInLoop(int, int) builder (after)
1199
1200## CHECK:  name             "B0"
1201## CHECK:  successors       "<<BSplit1:B\d+>>"
1202
1203## CHECK:  name             "<<BTry:B\d+>>"
1204## CHECK:  predecessors     "<<BEnterTry:B\d+>>"
1205## CHECK:  successors       "<<BExitTry:B\d+>>"
1206## CHECK:  Div
1207
1208## CHECK:  name             "<<BCatch:B\d+>>"
1209## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry>>"
1210## CHECK:  successors       "<<BEnterTry>>"
1211## CHECK:  flags            "catch_block"
1212
1213## CHECK:  name             "<<BEnterTry>>"
1214## CHECK:  predecessors     "<<BSplit1>>"
1215## CHECK:  successors       "<<BTry>>"
1216## CHECK:  xhandlers        "<<BCatch>>"
1217## CHECK:  TryBoundary      kind:entry
1218
1219## CHECK:  name             "<<BExitTry>>"
1220## CHECK:  predecessors     "<<BTry>>"
1221## CHECK:  successors       "<<BSplit2:B\d+>>"
1222## CHECK:  xhandlers        "<<BCatch>>"
1223## CHECK:  TryBoundary      kind:exit
1224
1225## CHECK:  name             "<<BSplit1>>"
1226## CHECK:  predecessors     "B0"
1227## CHECK:  successors       "<<BEnterTry>>"
1228## CHECK:  Goto
1229
1230## CHECK:  name             "<<BSplit2>>"
1231## CHECK:  predecessors     "<<BExitTry>>"
1232## CHECK:  successors       "<<BEnterTry>>"
1233## CHECK:  Goto
1234
1235.method public static testTryInLoop(II)I
1236    .registers 3
1237
1238    :try_start
1239    div-int/2addr p0, p1
1240    goto :try_start
1241    :try_end
1242    .catchall {:try_start .. :try_end} :catch_all
1243
1244    :catch_all
1245    goto :try_start
1246.end method
1247
1248# Test that a MOVE_RESULT instruction is placed into the same block as the
1249# INVOKE it follows, even if there is a try boundary between them.
1250
1251## CHECK-START: int Builder.testMoveResult_Invoke(int, int, int) builder (after)
1252## CHECK-DAG:     <<M1:i\d+>>  IntConstant -1
1253## CHECK-DAG:     <<Res:i\d+>> InvokeStaticOrDirect
1254## CHECK-DAG:     <<Phi:i\d+>> Phi [<<Res>>,<<M1>>]
1255## CHECK-DAG:                  Return [<<Phi>>]
1256
1257.method public static testMoveResult_Invoke(III)I
1258    .registers 3
1259
1260    :try_start
1261    invoke-static {p0, p1, p2}, LBuilder;->testCatchLoop(III)I
1262    :try_end
1263    .catchall {:try_start .. :try_end} :catch_all
1264
1265    move-result p0
1266
1267    :return
1268    return p0
1269
1270    :catch_all
1271    const/4 p0, -0x1
1272    goto :return
1273.end method
1274
1275# Test that a MOVE_RESULT instruction is placed into the same block as the
1276# FILLED_NEW_ARRAY it follows, even if there is a try boundary between them.
1277
1278## CHECK-START: int[] Builder.testMoveResult_FilledNewArray(int, int, int) builder (after)
1279## CHECK-DAG:     <<Arg1:i\d+>> ParameterValue
1280## CHECK-DAG:     <<Arg2:i\d+>> ParameterValue
1281## CHECK-DAG:     <<Arg3:i\d+>> ParameterValue
1282## CHECK-DAG:     <<Null:l\d+>> NullConstant
1283## CHECK-DAG:     <<Res:l\d+>>  NewArray
1284## CHECK-DAG:                   ArraySet   [<<Res>>,{{i\d+}},<<Arg1>>]
1285## CHECK-DAG:                   ArraySet   [<<Res>>,{{i\d+}},<<Arg2>>]
1286## CHECK-DAG:                   ArraySet   [<<Res>>,{{i\d+}},<<Arg3>>]
1287## CHECK-DAG:     <<Phi:l\d+>>  Phi [<<Res>>,<<Null>>]
1288## CHECK-DAG:                   Return [<<Phi>>]
1289
1290.method public static testMoveResult_FilledNewArray(III)[I
1291    .registers 3
1292
1293    :try_start
1294    filled-new-array {p0, p1, p2}, [I
1295    :try_end
1296    .catchall {:try_start .. :try_end} :catch_all
1297
1298    move-result-object p0
1299
1300    :return
1301    return-object p0
1302
1303    :catch_all
1304    const/4 p0, 0x0
1305    goto :return
1306.end method
1307
1308# Test case for ReturnVoid inside a try block. Builder needs to move it outside
1309# the try block so as to not split the ReturnVoid-Exit edge.
1310# This invariant is enforced by GraphChecker.
1311
1312.method public static testReturnVoidInTry(II)V
1313    .registers 2
1314
1315    :catch_all
1316    :try_start
1317    return-void
1318    :try_end
1319    .catchall {:try_start .. :try_end} :catch_all
1320.end method
1321
1322# Test case for Return inside a try block. Builder needs to move it outside the
1323# try block so as to not split the Return-Exit edge.
1324# This invariant is enforced by GraphChecker.
1325
1326.method public static testReturnInTry(II)I
1327    .registers 2
1328
1329    :try_start
1330    div-int/2addr p0, p1
1331    return p0
1332    :try_end
1333    .catchall {:try_start .. :try_end} :catch_all
1334
1335    :catch_all
1336    const/4 v0, 0x0
1337    return v0
1338.end method
1339
1340# Test a (dead) try block which flows out of the method. The block will be
1341# removed by DCE but needs to pass post-builder GraphChecker.
1342
1343## CHECK-START: int Builder.testDeadEndTry(int) builder (after)
1344## CHECK-NOT:     TryBoundary is_exit:true
1345
1346.method public static testDeadEndTry(I)I
1347    .registers 1
1348
1349    return p0
1350
1351    :catch_all
1352    nop
1353
1354    :try_start
1355    nop
1356    :try_end
1357    .catchall {:try_start .. :try_end} :catch_all
1358.end method
1359
1360# Test that a throw-catch loop on monitor-exit is eliminated.
1361# Note that we do not test this until after DCE which merges trivially split blocks.
1362
1363## CHECK-START: int Builder.testSynchronized(java.lang.Object) dead_code_elimination$initial (after)
1364## CHECK:      flags "catch_block"
1365## CHECK-NOT:  end_block
1366## CHECK:      MonitorOperation kind:exit
1367
1368.method public static testSynchronized(Ljava/lang/Object;)I
1369  .registers 2
1370
1371  monitor-enter p0
1372
1373  :try_start_9
1374  invoke-virtual {p0}, Ljava/lang/Object;->hashCode()I
1375  move-result v0
1376
1377  monitor-exit p0
1378  return v0
1379
1380  :catchall_11
1381  move-exception v0
1382  monitor-exit p0
1383  :try_end_15
1384  .catchall {:try_start_9 .. :try_end_15} :catchall_11
1385
1386  throw v0
1387.end method
1388