xref: /aosp_15_r20/art/test/482-checker-loop-back-edge-use/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker 
18*795d594fSAndroid Build Coastguard Worker public class Main {
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop1(boolean) liveness (after)
21*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:     <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>>  ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
22*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   If [<<Arg>>]    liveness:<<IfLiv:\d+>> loop:none
23*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto                                   loop:B{{\d+}}
24*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Exit
25*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
26*795d594fSAndroid Build Coastguard Worker   //
27*795d594fSAndroid Build Coastguard Worker   // Loop invariant exit check is hoisted from the loop by peeling.
28*795d594fSAndroid Build Coastguard Worker 
loop1(boolean incoming)29*795d594fSAndroid Build Coastguard Worker   public static void loop1(boolean incoming) {
30*795d594fSAndroid Build Coastguard Worker     while (incoming) {}
31*795d594fSAndroid Build Coastguard Worker   }
32*795d594fSAndroid Build Coastguard Worker 
33*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop2(boolean) liveness (after)
34*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:     <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
35*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   If [<<Arg>>]    liveness:<<IfLiv:\d+>>    loop:<<Loop1:B\d+>>
36*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv1:\d+>> loop:<<Loop1>>
37*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv2:\d+>> loop:<<Loop2:B\d+>>
38*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
39*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
40*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse>>
41*795d594fSAndroid Build Coastguard Worker   //
42*795d594fSAndroid Build Coastguard Worker   // Loop invariant exit check is hoisted from the loop by peeling.
43*795d594fSAndroid Build Coastguard Worker 
loop2(boolean incoming)44*795d594fSAndroid Build Coastguard Worker   public static void loop2(boolean incoming) {
45*795d594fSAndroid Build Coastguard Worker     // Add some code at entry to avoid having the entry block be a pre header.
46*795d594fSAndroid Build Coastguard Worker     // This avoids having to create a synthesized block.
47*795d594fSAndroid Build Coastguard Worker     System.out.println("Enter");
48*795d594fSAndroid Build Coastguard Worker     while (true) {
49*795d594fSAndroid Build Coastguard Worker       System.out.println("foo");
50*795d594fSAndroid Build Coastguard Worker       while (incoming) {}
51*795d594fSAndroid Build Coastguard Worker     }
52*795d594fSAndroid Build Coastguard Worker   }
53*795d594fSAndroid Build Coastguard Worker 
54*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop3(boolean) liveness (after)
55*795d594fSAndroid Build Coastguard Worker   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
56*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
57*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
58*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
59*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
60*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
61*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse>>
62*795d594fSAndroid Build Coastguard Worker 
loop3(boolean incoming)63*795d594fSAndroid Build Coastguard Worker   public static void loop3(boolean incoming) {
64*795d594fSAndroid Build Coastguard Worker     // 'incoming' only needs a use at the outer loop's back edge.
65*795d594fSAndroid Build Coastguard Worker     while (System.currentTimeMillis() != 42) {
66*795d594fSAndroid Build Coastguard Worker       while (Runtime.getRuntime() != null) {}
67*795d594fSAndroid Build Coastguard Worker       System.out.println(incoming);
68*795d594fSAndroid Build Coastguard Worker     }
69*795d594fSAndroid Build Coastguard Worker   }
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop4(boolean) liveness (after)
72*795d594fSAndroid Build Coastguard Worker   /// CHECK:         <<Arg:z\d+>> ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
73*795d594fSAndroid Build Coastguard Worker   /// CHECK:                      InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
74*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
75*795d594fSAndroid Build Coastguard Worker 
loop4(boolean incoming)76*795d594fSAndroid Build Coastguard Worker   public static void loop4(boolean incoming) {
77*795d594fSAndroid Build Coastguard Worker     // 'incoming' has no loop use, so should not have back edge uses.
78*795d594fSAndroid Build Coastguard Worker     System.out.println(incoming);
79*795d594fSAndroid Build Coastguard Worker     while (System.currentTimeMillis() != 42) {
80*795d594fSAndroid Build Coastguard Worker       while (Runtime.getRuntime() != null) {}
81*795d594fSAndroid Build Coastguard Worker     }
82*795d594fSAndroid Build Coastguard Worker   }
83*795d594fSAndroid Build Coastguard Worker 
84*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop5(boolean) liveness (after)
85*795d594fSAndroid Build Coastguard Worker   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse2:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse1:\d+>>,<<ArgLoopUse2>>]
86*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
87*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
88*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
89*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Exit
90*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
91*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
92*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse1>>
93*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse2>>
94*795d594fSAndroid Build Coastguard Worker 
loop5(boolean incoming)95*795d594fSAndroid Build Coastguard Worker   public static void loop5(boolean incoming) {
96*795d594fSAndroid Build Coastguard Worker     // 'incoming' must have a use at both back edges.
97*795d594fSAndroid Build Coastguard Worker     for (long i = System.nanoTime(); i < 42; ++i) {
98*795d594fSAndroid Build Coastguard Worker       for (long j = System.currentTimeMillis(); j != 42; ++j) {
99*795d594fSAndroid Build Coastguard Worker         System.out.println(incoming);
100*795d594fSAndroid Build Coastguard Worker       }
101*795d594fSAndroid Build Coastguard Worker     }
102*795d594fSAndroid Build Coastguard Worker   }
103*795d594fSAndroid Build Coastguard Worker 
104*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop6(boolean) liveness (after)
105*795d594fSAndroid Build Coastguard Worker   /// CHECK:         <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
106*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
107*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Add
108*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Goto            liveness:<<GotoLiv1:\d+>>
109*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Add
110*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Goto            liveness:<<GotoLiv2:\d+>>
111*795d594fSAndroid Build Coastguard Worker   /// CHECK:                       Exit
112*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse>>
113*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
114*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv2>> + 2 == <<ArgLoopUse>>
115*795d594fSAndroid Build Coastguard Worker 
loop6(boolean incoming)116*795d594fSAndroid Build Coastguard Worker   public static void loop6(boolean incoming) {
117*795d594fSAndroid Build Coastguard Worker     // 'incoming' must have a use only at the first loop's back edge.
118*795d594fSAndroid Build Coastguard Worker     for (long i = System.nanoTime(); i < 42; ++i) {
119*795d594fSAndroid Build Coastguard Worker       System.out.println(incoming);
120*795d594fSAndroid Build Coastguard Worker       for (long j = System.currentTimeMillis(); j != 42; ++j) {
121*795d594fSAndroid Build Coastguard Worker         System.out.print(j);  // non-empty body
122*795d594fSAndroid Build Coastguard Worker       }
123*795d594fSAndroid Build Coastguard Worker     }
124*795d594fSAndroid Build Coastguard Worker   }
125*795d594fSAndroid Build Coastguard Worker 
126*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop7(boolean) liveness (after)
127*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:     <<Arg:z\d+>>  ParameterValue  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse1:\d+>>,<<ArgUse2:\d+>>,<<ArgLoopUse>>]
128*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   InvokeVirtual   [{{l\d+}},<<Arg>>] method_name:java.io.PrintStream.println liveness:<<InvokeLiv:\d+>>
129*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   If              [<<Arg>>] liveness:<<IfLiv:\d+>> loop:<<Loop1:B\d+>>
130*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv1:\d+>>        loop:<<Loop1>>
131*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv2:\d+>>        loop:<<Loop2:B\d+>>
132*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Exit
133*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<InvokeLiv>> == <<ArgUse1>>
134*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse2>>
135*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
136*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse>>
137*795d594fSAndroid Build Coastguard Worker   //
138*795d594fSAndroid Build Coastguard Worker   // Loop invariant exit check is hoisted from the loop by peeling.
139*795d594fSAndroid Build Coastguard Worker 
loop7(boolean incoming)140*795d594fSAndroid Build Coastguard Worker   public static void loop7(boolean incoming) {
141*795d594fSAndroid Build Coastguard Worker     // 'incoming' must have a use at both back edges.
142*795d594fSAndroid Build Coastguard Worker     while (Runtime.getRuntime() != null) {
143*795d594fSAndroid Build Coastguard Worker       System.out.println(incoming);
144*795d594fSAndroid Build Coastguard Worker       while (incoming) {}
145*795d594fSAndroid Build Coastguard Worker       System.nanoTime();  // beat back edge splitting
146*795d594fSAndroid Build Coastguard Worker     }
147*795d594fSAndroid Build Coastguard Worker   }
148*795d594fSAndroid Build Coastguard Worker 
149*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop8() liveness (after)
150*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:     <<Arg:z\d+>>  StaticFieldGet  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopUse:\d+>>)} uses:[<<ArgUse:\d+>>,<<ArgLoopUse>>]
151*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   If [<<Arg>>]    liveness:<<IfLiv:\d+>>     loop:<<Loop1:B\d+>>
152*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv1:\d+>>  loop:<<Loop1>>
153*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv2:\d+>>  loop:<<Loop2:B\d+>>
154*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Exit
155*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
156*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
157*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> + 2 == <<ArgLoopUse>>
158*795d594fSAndroid Build Coastguard Worker   //
159*795d594fSAndroid Build Coastguard Worker   // Loop invariant exit check is hoisted from the loop by peeling.
160*795d594fSAndroid Build Coastguard Worker 
loop8()161*795d594fSAndroid Build Coastguard Worker   public static void loop8() {
162*795d594fSAndroid Build Coastguard Worker     // 'incoming' must have a use at both back edges.
163*795d594fSAndroid Build Coastguard Worker     boolean incoming = field;
164*795d594fSAndroid Build Coastguard Worker     while (Runtime.getRuntime() != null) {
165*795d594fSAndroid Build Coastguard Worker       System.nanoTime();  // beat pre-header creation
166*795d594fSAndroid Build Coastguard Worker       while (incoming) {}
167*795d594fSAndroid Build Coastguard Worker       System.nanoTime();  // beat back edge splitting
168*795d594fSAndroid Build Coastguard Worker     }
169*795d594fSAndroid Build Coastguard Worker   }
170*795d594fSAndroid Build Coastguard Worker 
171*795d594fSAndroid Build Coastguard Worker 
$opt$noinline$ensureSideEffects()172*795d594fSAndroid Build Coastguard Worker   static boolean $opt$noinline$ensureSideEffects() {
173*795d594fSAndroid Build Coastguard Worker     if (doThrow) throw new Error("");
174*795d594fSAndroid Build Coastguard Worker     return true;
175*795d594fSAndroid Build Coastguard Worker   }
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker   /// CHECK-START: void Main.loop9() liveness (after)
178*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:     <<Arg:z\d+>>  StaticFieldGet  liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgUse:\d+>>)} uses:[<<ArgUse>>]
179*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   If [<<Arg>>]    liveness:<<IfLiv:\d+>>     loop:<<Loop1:B\d+>>
180*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv1:\d+>>  loop:<<Loop1>>
181*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Goto            liveness:<<GotoLiv2:\d+>>  loop:<<Loop2:B\d+>>
182*795d594fSAndroid Build Coastguard Worker   /// CHECK-DAG:                   Exit
183*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<IfLiv>> + 1 == <<ArgUse>>
184*795d594fSAndroid Build Coastguard Worker   /// CHECK-EVAL:    <<GotoLiv1>> < <<GotoLiv2>>
185*795d594fSAndroid Build Coastguard Worker   //
186*795d594fSAndroid Build Coastguard Worker   // Loop invariant exit check is hoisted from the loop by peeling.
187*795d594fSAndroid Build Coastguard Worker 
loop9()188*795d594fSAndroid Build Coastguard Worker   public static void loop9() {
189*795d594fSAndroid Build Coastguard Worker     // Add some code at entry to avoid having the entry block be a pre header.
190*795d594fSAndroid Build Coastguard Worker     // This avoids having to create a synthesized block.
191*795d594fSAndroid Build Coastguard Worker     System.out.println("Enter");
192*795d594fSAndroid Build Coastguard Worker     while ($opt$noinline$ensureSideEffects()) {
193*795d594fSAndroid Build Coastguard Worker       // 'incoming' must only have a use in the inner loop.
194*795d594fSAndroid Build Coastguard Worker       boolean incoming = field;
195*795d594fSAndroid Build Coastguard Worker       while (incoming) {}
196*795d594fSAndroid Build Coastguard Worker     }
197*795d594fSAndroid Build Coastguard Worker   }
198*795d594fSAndroid Build Coastguard Worker 
main(String[] args)199*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) {
200*795d594fSAndroid Build Coastguard Worker   }
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   static boolean field;
203*795d594fSAndroid Build Coastguard Worker   static boolean doThrow = false;
204*795d594fSAndroid Build Coastguard Worker }
205