1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /**
18  * Regression tests for LICM.
19  */
20 public class Main {
21 
22   static int sA;
23 
24   //
25   // We cannot hoist the null check (can throw) above the field
26   // assignment (has write side effects) because that would result
27   // in throwing an exception before the assignment is done.
28   //
29   /// CHECK-START: void Main.foo(int[]) licm (before)
30   /// CHECK-DAG: LoadClass      loop:<<Loop:B\d+>> outer_loop:none
31   /// CHECK-DAG: StaticFieldSet loop:<<Loop>>      outer_loop:none
32   /// CHECK-DAG: NullCheck      loop:<<Loop>>      outer_loop:none
33   /// CHECK-DAG: ArrayLength    loop:<<Loop>>      outer_loop:none
34   //
35   /// CHECK-START: void Main.foo(int[]) licm (after)
36   /// CHECK-DAG: LoadClass      loop:none
37   /// CHECK-DAG: StaticFieldSet loop:<<Loop:B\d+>> outer_loop:none
38   /// CHECK-DAG: NullCheck      loop:<<Loop>>      outer_loop:none
39   /// CHECK-DAG: ArrayLength    loop:<<Loop>>      outer_loop:none
40   //
41   /// CHECK-START: void Main.foo(int[]) licm (after)
42   /// CHECK-NOT: LoadClass      loop:{{B\d+}} outer_loop:none
foo(int[] arr)43   static void foo(int[] arr) {
44     int j = 0;
45     do {
46       sA = 1;
47     } while (j < arr.length);
48   }
49 
50   //
51   // Similar situation as in foo(), but now a proper induction value
52   // is assigned to the field inside the do-while loop.
53   //
54   /// CHECK-START: void Main.bar(int[]) licm (before)
55   /// CHECK-DAG: LoadClass      loop:<<Loop:B\d+>> outer_loop:none
56   /// CHECK-DAG: StaticFieldSet loop:<<Loop>>      outer_loop:none
57   /// CHECK-DAG: NullCheck      loop:<<Loop>>      outer_loop:none
58   /// CHECK-DAG: ArrayLength    loop:<<Loop>>      outer_loop:none
59   //
60   /// CHECK-START: void Main.bar(int[]) licm (after)
61   /// CHECK-DAG: LoadClass      loop:none
62   /// CHECK-DAG: StaticFieldSet loop:<<Loop:B\d+>> outer_loop:none
63   /// CHECK-DAG: NullCheck      loop:<<Loop>>      outer_loop:none
64   /// CHECK-DAG: ArrayLength    loop:<<Loop>>      outer_loop:none
65   //
66   /// CHECK-START: void Main.bar(int[]) licm (after)
67   /// CHECK-NOT: LoadClass      loop:{{B\d+}} outer_loop:none
bar(int[] arr)68   static void bar(int[] arr) {
69     int j = 0;
70     do {
71       j++;
72       sA = j;
73     } while (j < arr.length);
74   }
75 
76   //
77   // Similar situation as in bar(), but now an explicit catch
78   // statement may need the latest value of local j.
79   //
80   /// CHECK-START: int Main.catcher(int[]) licm (before)
81   /// CHECK-DAG: NullCheck   loop:<<Loop:B\d+>> outer_loop:none
82   /// CHECK-DAG: ArrayLength loop:<<Loop>>      outer_loop:none
83   //
84   /// CHECK-START: int Main.catcher(int[]) licm (after)
85   /// CHECK-DAG: NullCheck   loop:<<Loop:B\d+>> outer_loop:none
86   /// CHECK-DAG: ArrayLength loop:<<Loop>>      outer_loop:none
catcher(int[] arr)87   static int catcher(int[] arr) {
88     int j = 0;
89     try {
90       do {
91         j++;
92       } while (j < arr.length);
93     } catch (NullPointerException e) {
94       return -j;  // flag exception with negative value
95     }
96     return j;
97   }
98 
main(String[] args)99   public static void main(String[] args) {
100     sA = 0;
101     try {
102       foo(null);
103       throw new Error("Expected NPE");
104     } catch (NullPointerException e) {
105     }
106     expectEquals(1, sA);
107 
108     sA = 0;
109     try {
110       bar(null);
111       throw new Error("Expected NPE");
112     } catch (NullPointerException e) {
113     }
114     expectEquals(1, sA);
115 
116     for (int i = 0; i < 5; i++) {
117       sA = 0;
118       bar(new int[i]);
119       expectEquals(i == 0 ? 1 : i, sA);
120     }
121 
122     expectEquals(-1, catcher(null));
123     for (int i = 0; i < 5; i++) {
124       expectEquals(i == 0 ? 1 : i, catcher(new int[i]));
125     }
126 
127     System.out.println("passed");
128   }
129 
expectEquals(int expected, int result)130   private static void expectEquals(int expected, int result) {
131     if (expected != result) {
132       throw new Error("Expected: " + expected + ", found: " + result);
133     }
134   }
135 }
136