1 /*
2  * Copyright (C) 2015 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 public class Main {
19 
20   /// CHECK-START: void Main.loop1(boolean) liveness (after)
21   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>>  ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
22   /// CHECK:                       If [<<Arg>>]    liveness:<<IfLiv:\d+>>
23   /// CHECK:                       Goto            liveness:<<GotoLiv:\d+>>
24   /// CHECK:                       Exit
25   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
26   /// CHECK-EVAL:    <<GotoLiv>> + 2 == <<ArgLoopUse>>
27 
loop1(boolean incoming)28   public static void loop1(boolean incoming) {
29     while (incoming) {}
30   }
31 
32   /// CHECK-START: void Main.loop2(boolean) liveness (after)
33   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse2:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse1:\d+>>,<<ArgLoopUse2>>]
34   /// CHECK:                       If [<<Arg>>]    liveness:<<IfLiv:\d+>>
35   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
36   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
37   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
38   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
39   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse1>>
40   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse2>>
41 
loop2(boolean incoming)42   public static void loop2(boolean incoming) {
43     // Add some code at entry to avoid having the entry block be a pre header.
44     // This avoids having to create a synthesized block.
45     System.out.println("Enter");
46     while (true) {
47       System.out.println("foo");
48       while (incoming) {}
49     }
50   }
51 
52   /// CHECK-START: void Main.loop3(boolean) liveness (after)
53   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
54   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
55   /// CHECK:                       InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
56   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
57   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
58   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
59   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse>>
60 
loop3(boolean incoming)61   public static void loop3(boolean incoming) {
62     // 'incoming' only needs a use at the outer loop's back edge.
63     while (System.currentTimeMillis() != 42) {
64       while (Runtime.getRuntime() != null) {}
65       System.out.println(incoming);
66     }
67   }
68 
69   /// CHECK-START: void Main.loop4(boolean) liveness (after)
70   /// CHECK:         <<Arg:z\d+>> ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
71   /// CHECK:                      InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
72   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
73 
loop4(boolean incoming)74   public static void loop4(boolean incoming) {
75     // 'incoming' has no loop use, so should not have back edge uses.
76     System.out.println(incoming);
77     while (System.currentTimeMillis() != 42) {
78       while (Runtime.getRuntime() != null) {}
79     }
80   }
81 
82   /// CHECK-START: void Main.loop5(boolean) liveness (after)
83   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse2:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse1:\d+>>,<<ArgLoopUse2>>]
84   /// CHECK:                       InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
85   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
86   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
87   /// CHECK:                       Exit
88   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
89   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
90   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse1>>
91   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse2>>
92 
loop5(boolean incoming)93   public static void loop5(boolean incoming) {
94     // 'incoming' must have a use at both back edges.
95     for (long i = System.nanoTime(); i < 42; ++i) {
96       for (long j = System.currentTimeMillis(); j != 42; ++j) {
97         System.out.println(incoming);
98       }
99     }
100   }
101 
102   /// CHECK-START: void Main.loop6(boolean) liveness (after)
103   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
104   /// CHECK:                       InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
105   /// CHECK:                       Add
106   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
107   /// CHECK:                       Add
108   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
109   /// CHECK:                       Exit
110   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
111   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
112   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse>>
113 
loop6(boolean incoming)114   public static void loop6(boolean incoming) {
115     // 'incoming' must have a use only at the first loop's back edge.
116     for (long i = System.nanoTime(); i < 42; ++i) {
117       System.out.println(incoming);
118       for (long j = System.currentTimeMillis(); j != 42; ++j) {
119         System.out.print(j);  // non-empty body
120       }
121     }
122   }
123 
124   /// CHECK-START: void Main.loop7(boolean) liveness (after)
125   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse2:\d+>>)} uses:[<<ArgUse1:\d+>>,<<ArgUse2:\d+>>,<<ArgLoopUse1:\d+>>,<<ArgLoopUse2>>]
126   /// CHECK:                       InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
127   /// CHECK:                       If              [<<Arg>>] liveness:<<IfLiv:\d+>>
128   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
129   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
130   /// CHECK:                       Exit
131   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse1>>
132   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse2>>
133   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
134   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse1>>
135   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse2>>
136 
loop7(boolean incoming)137   public static void loop7(boolean incoming) {
138     // 'incoming' must have a use at both back edges.
139     while (Runtime.getRuntime() != null) {
140       System.out.println(incoming);
141       while (incoming) {}
142       System.nanoTime();  // beat back edge splitting
143     }
144   }
145 
146   /// CHECK-START: void Main.loop8() liveness (after)
147   /// CHECK:         <<Arg:z\d+>>  StaticFieldGet  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse2:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse1:\d+>>,<<ArgLoopUse2>>]
148   /// CHECK:                       If [<<Arg>>]    liveness:<<IfLiv:\d+>>
149   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
150   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
151   /// CHECK:                       Exit
152   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
153   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
154   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse1>>
155   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse2>>
156 
loop8()157   public static void loop8() {
158     // 'incoming' must have a use at both back edges.
159     boolean incoming = field;
160     while (Runtime.getRuntime() != null) {
161       System.nanoTime();  // beat pre-header creation
162       while (incoming) {}
163       System.nanoTime();  // beat back edge splitting
164     }
165   }
166 
167 
$opt$noinline$ensureSideEffects()168   static boolean $opt$noinline$ensureSideEffects() {
169     if (doThrow) throw new Error("");
170     return true;
171   }
172 
173   /// CHECK-START: void Main.loop9() liveness (after)
174   /// CHECK:         <<Arg:z\d+>>  StaticFieldGet  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
175   /// CHECK:                       If [<<Arg>>]    liveness:<<IfLiv:\d+>>
176   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
177   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv2:\d+>>
178   /// CHECK-DAG:                   Exit
179   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
180   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
181   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse>>
182 
loop9()183   public static void loop9() {
184     // Add some code at entry to avoid having the entry block be a pre header.
185     // This avoids having to create a synthesized block.
186     System.out.println("Enter");
187     while ($opt$noinline$ensureSideEffects()) {
188       // 'incoming' must only have a use in the inner loop.
189       boolean incoming = field;
190       while (incoming) {}
191     }
192   }
193 
main(String[] args)194   public static void main(String[] args) {
195   }
196 
197   static boolean field;
198   static boolean doThrow = false;
199 }
200