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