• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 public class Main {
18     private int intField;
19 
main(String[] args)20     public static void main(String[] args) {
21         System.out.print("IfXLtzAElseB(-7): ");
22         $noinline$IfXLtzAElseB(-7);
23         System.out.print("IfXLtzAElseB(42): ");
24         $noinline$IfXLtzAElseB(42);
25 
26         System.out.print("IfXLtzAElseB_Move(-7): ");
27         new Main().$noinline$IfXLtzAElseB_Move(-7);
28         System.out.print("IfXLtzAElseB_Move(42): ");
29         new Main().$noinline$IfXLtzAElseB_Move(42);
30 
31         System.out.print("IfXLtzAElseB_EnvUse(-7): ");
32         $noinline$IfXLtzAElseB_EnvUse(-7);
33         System.out.print("IfXLtzAElseB_EnvUse(42): ");
34         $noinline$IfXLtzAElseB_EnvUse(42);
35 
36         System.out.print("IfXNullAElseB(null): ");
37         $noinline$IfXNullAElseB(null);
38         System.out.print("IfXNullAElseB(new Object()): ");
39         $noinline$IfXNullAElseB(new Object());
40 
41         System.out.print("IfXNullAElseB_Move(null): ");
42         new Main().$noinline$IfXNullAElseB_Move(null);
43         System.out.print("IfXNullAElseB_Move(new Object()): ");
44         new Main().$noinline$IfXNullAElseB_Move(new Object());
45 
46         System.out.print("IfXNullAElseB_EnvUse(null): ");
47         new Main().$noinline$IfXNullAElseB_EnvUse(null);
48         System.out.print("IfXNullAElseB_EnvUse(new Object()): ");
49         new Main().$noinline$IfXNullAElseB_EnvUse(new Object());
50 
51         System.out.print("IfXNullAElseB_RefNoEnvInBlock(null, true): ");
52         new Main().$noinline$IfXNullAElseB_RefNoEnvInBlock(null, true);
53         System.out.print("IfXNullAElseB_RefNoEnvInBlock(new Object(), true): ");
54         new Main().$noinline$IfXNullAElseB_RefNoEnvInBlock(new Object(), true);
55         System.out.print("IfXNullAElseB_RefNoEnvInBlock(null, false): ");
56         new Main().$noinline$IfXNullAElseB_RefNoEnvInBlock(null, false);
57         System.out.print("IfXNullAElseB_RefNoEnvInBlock(new Object(), false): ");
58         new Main().$noinline$IfXNullAElseB_RefNoEnvInBlock(new Object(), false);
59 
60         System.out.print("IfLt7_0AElseB_86LoadFromConstantTable(2.0, true): ");
61         new Main().$noinline$IfLt7_0AElseB_86LoadFromConstantTable(2.0, true);
62         System.out.print("IfLt7_0AElseB_86LoadFromConstantTable(10.0, true): ");
63         new Main().$noinline$IfLt7_0AElseB_86LoadFromConstantTable(10.0, true);
64         System.out.print("IfLt7_0AElseB_86LoadFromConstantTable(2.0, false): ");
65         new Main().$noinline$IfLt7_0AElseB_86LoadFromConstantTable(2.0, false);
66         System.out.print("IfLt7_0AElseB_86LoadFromConstantTable(10.0, false): ");
67         new Main().$noinline$IfLt7_0AElseB_86LoadFromConstantTable(10.0, false);
68 
69         // Note: We do not test the code paths where `ConditionMoveWouldExtendReferenceLifetime()`
70         // in the "prepare_for_register_allocation" pass finds an instruction with environment
71         // between the `HCondition` and its user in this run-test. These are difficult to create
72         // from Java code and changes to other passes can easily invalidate such tests. Therefore
73         // we defer to using gtests for these cases.
74     }
75 
$noinline$A()76     private static void $noinline$A() {
77         System.out.println("A");
78     }
79 
$noinline$B()80     private static void $noinline$B() {
81         System.out.println("B");
82     }
83 
$noinline$C()84     private static void $noinline$C() {
85         System.out.println("C");
86     }
87 
$inline$XLtz(int x)88     private static boolean $inline$XLtz(int x) {
89         // After inlining, this shall be turned to a `HSelect` and then simplified as `HLessThan`.
90         return x < 0;
91     }
92 
$inline$XNull(Object x)93     private static boolean $inline$XNull(Object x) {
94         // After inlining, this shall be turned to a `HSelect` and then simplified as `HEqual`.
95         return x == null;
96     }
97 
$inline$XLt7_0(double x)98     private static boolean $inline$XLt7_0(double x) {
99         return x < 7.0;
100     }
101 
$noinline$ignore(int ignored)102     private static void $noinline$ignore(int ignored) {}
103 
104     /// CHECK-START: void Main.$noinline$IfXLtzAElseB(int) prepare_for_register_allocation (before)
105     /// CHECK:      <<Cond:z\d+>> {{GreaterThanOrEqual|LessThan}} emitted_at_use_site:false
106     /// CHECK-NEXT:               If [<<Cond>>]
107 
108     /// CHECK-START: void Main.$noinline$IfXLtzAElseB(int) prepare_for_register_allocation (after)
109     /// CHECK:      <<Cond:z\d+>> {{GreaterThanOrEqual|LessThan}} emitted_at_use_site:true
110     /// CHECK-NEXT:               If [<<Cond>>]
111 
$noinline$IfXLtzAElseB(int x)112     public static void $noinline$IfXLtzAElseB(int x) {
113         if (x < 0) {
114             $noinline$A();
115         } else {
116             $noinline$B();
117         }
118     }
119 
120     /// CHECK-START: void Main.$noinline$IfXLtzAElseB_Move(int) prepare_for_register_allocation (before)
121     /// CHECK:      <<Cond:z\d+>> LessThan emitted_at_use_site:false
122     /// CHECK-NEXT:               InstanceFieldGet
123     // On X86, there can be also X86ComputeBaseMethodAddress here.
124     /// CHECK:                    If [<<Cond>>]
125 
126     /// CHECK-START: void Main.$noinline$IfXLtzAElseB_Move(int) prepare_for_register_allocation (after)
127     /// CHECK:                    InstanceFieldGet
128     // On X86, there can be also X86ComputeBaseMethodAddress here.
129     /// CHECK:      <<Cond:z\d+>> LessThan emitted_at_use_site:true
130     /// CHECK-NEXT:               If [<<Cond>>]
131 
$noinline$IfXLtzAElseB_Move(int x)132     public void $noinline$IfXLtzAElseB_Move(int x) {
133         boolean cond = $inline$XLtz(x);
134 
135         int value = intField;
136         if (cond) {
137             cond = false;  // Avoid environment use below.
138             $noinline$A();
139         } else {
140             cond = false;  // Avoid environment use below.
141             $noinline$B();
142         }
143         $noinline$ignore(value);
144     }
145 
146     /// CHECK-START: void Main.$noinline$IfXLtzAElseB_EnvUse(int) prepare_for_register_allocation (before)
147     /// CHECK:                    LessThan emitted_at_use_site:false
148 
149     /// CHECK-START: void Main.$noinline$IfXLtzAElseB_EnvUse(int) prepare_for_register_allocation (after)
150     /// CHECK-DAG:  <<Cond:z\d+>> LessThan emitted_at_use_site:false
151     // Match an environment use. Use the fact that the <<Cond>> is in vreg 0. Otherwise we'd
152     // need to add a regex to match the earlier vregs which is difficult due to a regex eagerly
153     // consuming as much as possible but it could be curtailed by using the fact that there
154     // are no other boolean (`z`) values in the graph, for example with `{{([^z,]+,)*}}`. This
155     // would be much easier if we could put a variable inside the regex and make the entire
156     // env uses a single regex, `env:[[{{([^,]+,)*<<Cond>>(,[^,\]]+)*}}]]`.
157     /// CHECK-DAG:                InvokeStaticOrDirect env:[[<<Cond>>{{(,[^,\]]+)*}}]]
158 
$noinline$IfXLtzAElseB_EnvUse(int x)159     public static void $noinline$IfXLtzAElseB_EnvUse(int x) {
160         boolean cond = $inline$XLtz(x);
161         if (cond) {
162             $noinline$A();
163         } else {
164             $noinline$B();
165         }
166     }
167 
168     /// CHECK-START: void Main.$noinline$IfXNullAElseB(java.lang.Object) prepare_for_register_allocation (before)
169     /// CHECK:      <<Cond:z\d+>> {{Equal|NotEqual}} emitted_at_use_site:false
170     /// CHECK-NEXT:               If [<<Cond>>]
171 
172     /// CHECK-START: void Main.$noinline$IfXNullAElseB(java.lang.Object) prepare_for_register_allocation (after)
173     /// CHECK:      <<Cond:z\d+>> {{Equal|NotEqual}} emitted_at_use_site:true
174     /// CHECK-NEXT:               If [<<Cond>>]
175 
$noinline$IfXNullAElseB(Object x)176     public static void $noinline$IfXNullAElseB(Object x) {
177         if (x == null) {
178             $noinline$A();
179         } else {
180             $noinline$B();
181         }
182     }
183 
184     /// CHECK-START: void Main.$noinline$IfXNullAElseB_Move(java.lang.Object) prepare_for_register_allocation (before)
185     /// CHECK:      <<Cond:z\d+>> Equal emitted_at_use_site:false
186     /// CHECK-NEXT:               InstanceFieldGet
187     // On X86, there can be also X86ComputeBaseMethodAddress here.
188     /// CHECK:                    If [<<Cond>>]
189 
190     /// CHECK-START: void Main.$noinline$IfXNullAElseB_Move(java.lang.Object) prepare_for_register_allocation (after)
191     /// CHECK:                    InstanceFieldGet
192     // On X86, there can be also X86ComputeBaseMethodAddress here.
193     /// CHECK:      <<Cond:z\d+>> Equal emitted_at_use_site:true
194     /// CHECK-NEXT:               If [<<Cond>>]
195 
$noinline$IfXNullAElseB_Move(Object x)196     public void $noinline$IfXNullAElseB_Move(Object x) {
197         boolean cond = $inline$XNull(x);
198 
199         int value = intField;
200         if (cond) {
201             cond = false;  // Avoid environment use below.
202             $noinline$A();
203         } else {
204             cond = false;  // Avoid environment use below.
205             $noinline$B();
206         }
207         $noinline$ignore(value);
208     }
209 
210     /// CHECK-START: void Main.$noinline$IfXNullAElseB_EnvUse(java.lang.Object) prepare_for_register_allocation (before)
211     /// CHECK:                    Equal emitted_at_use_site:false
212 
213     /// CHECK-START: void Main.$noinline$IfXNullAElseB_EnvUse(java.lang.Object) prepare_for_register_allocation (after)
214     /// CHECK:                    Equal emitted_at_use_site:false
215 
$noinline$IfXNullAElseB_EnvUse(Object x)216     public static void $noinline$IfXNullAElseB_EnvUse(Object x) {
217         boolean cond = $inline$XNull(x);
218         if (cond) {
219             $noinline$A();
220         } else {
221             $noinline$B();
222         }
223     }
224 
225     /// CHECK-START: void Main.$noinline$IfXNullAElseB_RefNoEnvInBlock(java.lang.Object, boolean) prepare_for_register_allocation (before)
226     /// CHECK:      <<Cond:z\d+>> {{Equal|NotEqual}} emitted_at_use_site:false
227     /// CHECK:                    If [<<Cond>>]
228 
229     /// CHECK-START: void Main.$noinline$IfXNullAElseB_RefNoEnvInBlock(java.lang.Object, boolean) prepare_for_register_allocation (after)
230     /// CHECK:      <<Cond:z\d+>> {{Equal|NotEqual}} emitted_at_use_site:false
231     /// CHECK:                    If [<<Cond>>]
232 
$noinline$IfXNullAElseB_RefNoEnvInBlock(Object x, boolean otherCond)233     public static void $noinline$IfXNullAElseB_RefNoEnvInBlock(Object x, boolean otherCond) {
234         boolean cond = $inline$XNull(x);
235         if (otherCond) {
236             if (cond) {
237                 cond = false;  // Avoid environment use below.
238                 $noinline$A();
239             } else {
240                 cond = false;  // Avoid environment use below.
241                 $noinline$B();
242             }
243         } else {
244             cond = false;  // Avoid environment use below.
245             $noinline$C();
246         }
247     }
248 
249     /// CHECK-START: void Main.$noinline$IfLt7_0AElseB_86LoadFromConstantTable(double, boolean) prepare_for_register_allocation (before)
250     /// CHECK:      <<Cond:z\d+>> {{LessThan|GreaterThanOrEqual}} emitted_at_use_site:false
251     /// CHECK:                    If [<<Cond>>]
252 
253     /// CHECK-START: void Main.$noinline$IfLt7_0AElseB_86LoadFromConstantTable(double, boolean) prepare_for_register_allocation (after)
254     /// CHECK:      <<Cond:z\d+>> {{LessThan|GreaterThanOrEqual}} emitted_at_use_site:true
255     /// CHECK-NEXT:               If [<<Cond>>]
256 
257     /// CHECK-START-X86: void Main.$noinline$IfLt7_0AElseB_86LoadFromConstantTable(double, boolean) prepare_for_register_allocation (after)
258     /// CHECK:                    X86ComputeBaseMethodAddress
259     // Note: X86ComputeBaseMethodAddress is not moved before X86LoadFromConstantTable because
260     // it has additional uses in all the `$noinline$` invokes.
261     /// CHECK:                    X86LoadFromConstantTable
262     /// CHECK-NEXT: <<Cond:z\d+>> {{LessThan|GreaterThanOrEqual}} emitted_at_use_site:true
263     /// CHECK-NEXT:               If [<<Cond>>]
264 
265     /// CHECK-START-X86: void Main.$noinline$IfLt7_0AElseB_86LoadFromConstantTable(double, boolean) prepare_for_register_allocation (after)
266     /// CHECK-DAG: <<MA:i\d+>>    X86ComputeBaseMethodAddress
267     /// CHECK-DAG:                InvokeStaticOrDirect [<<MA>>]
268 
$noinline$IfLt7_0AElseB_86LoadFromConstantTable( double x, boolean otherCond)269     public static void $noinline$IfLt7_0AElseB_86LoadFromConstantTable(
270             double x, boolean otherCond) {
271         boolean cond = $inline$XLt7_0(x);
272         if (otherCond) {
273             if (cond) {
274                 cond = false;  // Avoid environment use below.
275                 $noinline$A();
276             } else {
277                 cond = false;  // Avoid environment use below.
278                 $noinline$B();
279             }
280         } else {
281             cond = false;  // Avoid environment use below.
282             $noinline$C();
283         }
284     }
285 }
286