• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 {
main(String[] args)18     public static void main(String[] args) throws Exception {
19         assertEquals(40, $noinline$testEliminateIf(20, 40));
20         assertEquals(30, $noinline$testEliminateIf(20, 10));
21         assertEquals(40, $noinline$testEliminateIfTwiceInARow(20, 40));
22         assertEquals(30, $noinline$testEliminateIfTwiceInARow(20, 10));
23         assertEquals(40, $noinline$testEliminateIfThreePredecessors(20, 40));
24         assertEquals(30, $noinline$testEliminateIfThreePredecessors(20, 10));
25         assertEquals(40, $noinline$testEliminateIfOppositeCondition(20, 40));
26         assertEquals(30, $noinline$testEliminateIfOppositeCondition(20, 10));
27         assertEquals(40, $noinline$testEliminateIfParameter(20, 40, 20 < 40));
28         assertEquals(30, $noinline$testEliminateIfParameter(20, 10, 20 < 10));
29         assertEquals(40, $noinline$testEliminateIfParameterReverseCondition(20, 40, 20 < 40));
30         assertEquals(30, $noinline$testEliminateIfParameterReverseCondition(20, 10, 20 < 10));
31         assertEquals(40, $noinline$testEliminateIfParameterOppositeCondition(20, 40, 20 < 40));
32         assertEquals(30, $noinline$testEliminateIfParameterOppositeCondition(20, 10, 20 < 10));
33         assertEquals(40, $noinline$testEliminateIfParameterOppositeCondition_2(20, 40, 20 < 40));
34         assertEquals(30, $noinline$testEliminateIfParameterOppositeCondition_2(20, 10, 20 < 10));
35 
36         assertEquals(2, $noinline$testEliminateIfFp(20.0, 40.0));
37         assertEquals(3, $noinline$testEliminateIfFp(20.0, 10.0));
38         assertEquals(3, $noinline$testEliminateIfFp(20.0, Double.NaN));
39         assertEquals(3, $noinline$testEliminateIfFp(Double.NaN, 10.0));
40         assertEquals(3, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(20.0, 40.0));
41         assertEquals(2, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(20.0, 10.0));
42         assertEquals(3, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(20.0, Double.NaN));
43         assertEquals(3, $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(Double.NaN, 10.0));
44     }
45 
$noinline$emptyMethod(int a)46     private static int $noinline$emptyMethod(int a) {
47         return a;
48     }
49 
50     /// CHECK-START: int Main.$noinline$testEliminateIf(int, int) dead_code_elimination$after_gvn (before)
51     /// CHECK:     If
52     /// CHECK:     If
53 
54     /// CHECK-START: int Main.$noinline$testEliminateIf(int, int) dead_code_elimination$after_gvn (after)
55     /// CHECK:     If
56     /// CHECK-NOT: If
$noinline$testEliminateIf(int a, int b)57     private static int $noinline$testEliminateIf(int a, int b) {
58         int result = 0;
59         if (a < b) {
60             $noinline$emptyMethod(a + b);
61         } else {
62             $noinline$emptyMethod(a - b);
63         }
64         if (a < b) {
65             result += $noinline$emptyMethod(a * 2);
66         } else {
67             result += $noinline$emptyMethod(b * 3);
68         }
69         return result;
70     }
71 
72     /// CHECK-START: int Main.$noinline$testEliminateIfTwiceInARow(int, int) dead_code_elimination$after_gvn (before)
73     /// CHECK:     If
74     /// CHECK:     If
75     /// CHECK:     If
76 
77     /// CHECK-START: int Main.$noinline$testEliminateIfTwiceInARow(int, int) dead_code_elimination$after_gvn (after)
78     /// CHECK:     If
79     /// CHECK-NOT: If
$noinline$testEliminateIfTwiceInARow(int a, int b)80     private static int $noinline$testEliminateIfTwiceInARow(int a, int b) {
81         int result = 0;
82         if (a < b) {
83             $noinline$emptyMethod(a + b);
84         } else {
85             $noinline$emptyMethod(a - b);
86         }
87         if (a < b) {
88             $noinline$emptyMethod(a * 2);
89         } else {
90             $noinline$emptyMethod(b * 3);
91         }
92         if (a < b) {
93             result += $noinline$emptyMethod(40);
94         } else {
95             result += $noinline$emptyMethod(30);
96         }
97         return result;
98     }
99 
100     /// CHECK-START: int Main.$noinline$testEliminateIfThreePredecessors(int, int) dead_code_elimination$after_gvn (before)
101     /// CHECK:     If
102     /// CHECK:     If
103     /// CHECK:     If
104 
105     /// CHECK-START: int Main.$noinline$testEliminateIfThreePredecessors(int, int) dead_code_elimination$after_gvn (after)
106     /// CHECK:     If
107     /// CHECK:     If
108     /// CHECK-NOT: If
$noinline$testEliminateIfThreePredecessors(int a, int b)109     private static int $noinline$testEliminateIfThreePredecessors(int a, int b) {
110         int result = 0;
111         if (a < b) {
112             $noinline$emptyMethod(a + b);
113         } else {
114             if (b < 5) {
115                 $noinline$emptyMethod(a - b);
116             } else {
117                 $noinline$emptyMethod(a * b);
118             }
119         }
120         if (a < b) {
121             result += $noinline$emptyMethod(a * 2);
122         } else {
123             result += $noinline$emptyMethod(b * 3);
124         }
125         return result;
126     }
127 
128     // Note that we can perform this optimization in dead_code_elimination$initial since we don't
129     // rely on gvn to de-duplicate the values.
130 
131     /// CHECK-START: int Main.$noinline$testEliminateIfOppositeCondition(int, int) dead_code_elimination$initial (before)
132     /// CHECK:     If
133     /// CHECK:     If
134 
135     /// CHECK-START: int Main.$noinline$testEliminateIfOppositeCondition(int, int) dead_code_elimination$initial (after)
136     /// CHECK:     If
137     /// CHECK-NOT: If
$noinline$testEliminateIfOppositeCondition(int a, int b)138     private static int $noinline$testEliminateIfOppositeCondition(int a, int b) {
139         int result = 0;
140         if (a < b) {
141             $noinline$emptyMethod(a + b);
142         } else {
143             $noinline$emptyMethod(a - b);
144         }
145         if (a >= b) {
146             result += $noinline$emptyMethod(b * 3);
147         } else {
148             result += $noinline$emptyMethod(a * 2);
149         }
150         return result;
151     }
152 
153     // In this scenario, we have a BooleanNot before the If instructions so we have to wait until
154     // the following pass to perform the optimization. The BooleanNot is dead at this time (even
155     // when starting DCE), but RemoveDeadInstructions runs after SimplifyIfs so the optimization
156     // doesn't trigger.
157 
158     /// CHECK-START: int Main.$noinline$testEliminateIfParameter(int, int, boolean) dead_code_elimination$initial (before)
159     /// CHECK:     BooleanNot
160     /// CHECK:     If
161     /// CHECK:     BooleanNot
162     /// CHECK:     If
163 
164     /// CHECK-START: int Main.$noinline$testEliminateIfParameter(int, int, boolean) dead_code_elimination$initial (after)
165     /// CHECK:     If
166     /// CHECK:     Phi
167     /// CHECK:     If
168 
169     /// CHECK-START: int Main.$noinline$testEliminateIfParameter(int, int, boolean) dead_code_elimination$initial (after)
170     /// CHECK-NOT: BooleanNot
171 
172     /// CHECK-START: int Main.$noinline$testEliminateIfParameter(int, int, boolean) dead_code_elimination$after_gvn (before)
173     /// CHECK:     If
174     /// CHECK:     Phi
175     /// CHECK:     If
176 
177     /// CHECK-START: int Main.$noinline$testEliminateIfParameter(int, int, boolean) dead_code_elimination$after_gvn (after)
178     /// CHECK:     If
179     /// CHECK-NOT: If
$noinline$testEliminateIfParameter(int a, int b, boolean condition)180     private static int $noinline$testEliminateIfParameter(int a, int b, boolean condition) {
181         int result = 0;
182         if (condition) {
183             $noinline$emptyMethod(a + b);
184         } else {
185             $noinline$emptyMethod(a - b);
186         }
187         if (condition) {
188             result += $noinline$emptyMethod(a * 2);
189         } else {
190             result += $noinline$emptyMethod(b * 3);
191         }
192         return result;
193     }
194 
195     // Same in the following two cases: we do it in dead_code_elimination$initial since GVN is not
196     // needed.
197 
198     /// CHECK-START: int Main.$noinline$testEliminateIfParameterReverseCondition(int, int, boolean) dead_code_elimination$initial (before)
199     /// CHECK:     If
200     /// CHECK:     If
201 
202     /// CHECK-START: int Main.$noinline$testEliminateIfParameterReverseCondition(int, int, boolean) dead_code_elimination$initial (after)
203     /// CHECK:     If
204     /// CHECK-NOT: If
$noinline$testEliminateIfParameterReverseCondition( int a, int b, boolean condition)205     private static int $noinline$testEliminateIfParameterReverseCondition(
206             int a, int b, boolean condition) {
207         int result = 0;
208         if (!condition) {
209             $noinline$emptyMethod(a + b);
210         } else {
211             $noinline$emptyMethod(a - b);
212         }
213         if (!condition) {
214             result += $noinline$emptyMethod(b * 3);
215         } else {
216             result += $noinline$emptyMethod(a * 2);
217         }
218         return result;
219     }
220 
221     /// CHECK-START: int Main.$noinline$testEliminateIfParameterOppositeCondition(int, int, boolean) dead_code_elimination$initial (before)
222     /// CHECK:     If
223     /// CHECK:     If
224 
225     /// CHECK-START: int Main.$noinline$testEliminateIfParameterOppositeCondition(int, int, boolean) dead_code_elimination$initial (after)
226     /// CHECK:     If
227     /// CHECK-NOT: If
$noinline$testEliminateIfParameterOppositeCondition( int a, int b, boolean condition)228     private static int $noinline$testEliminateIfParameterOppositeCondition(
229             int a, int b, boolean condition) {
230         int result = 0;
231         if (condition) {
232             $noinline$emptyMethod(a + b);
233         } else {
234             $noinline$emptyMethod(a - b);
235         }
236         if (!condition) {
237             result += $noinline$emptyMethod(b * 3);
238         } else {
239             result += $noinline$emptyMethod(a * 2);
240         }
241         return result;
242     }
243 
244     // In this scenario, we have a BooleanNot before the If instructions so we have to wait until
245     // the following pass to perform the optimization. The BooleanNot is dead at this time (even
246     // when starting DCE), but RemoveDeadInstructions runs after SimplifyIfs so the optimization
247     // doesn't trigger.
248 
249     /// CHECK-START: int Main.$noinline$testEliminateIfParameterOppositeCondition_2(int, int, boolean) dead_code_elimination$initial (before)
250     /// CHECK:     If
251     /// CHECK:     BooleanNot
252     /// CHECK:     If
253 
254     /// CHECK-START: int Main.$noinline$testEliminateIfParameterOppositeCondition_2(int, int, boolean) dead_code_elimination$initial (after)
255     /// CHECK:     If
256     /// CHECK:     Phi
257     /// CHECK:     If
258 
259     /// CHECK-START: int Main.$noinline$testEliminateIfParameterOppositeCondition_2(int, int, boolean) dead_code_elimination$initial (after)
260     /// CHECK-NOT: BooleanNot
261 
262     /// CHECK-START: int Main.$noinline$testEliminateIfParameterOppositeCondition_2(int, int, boolean) dead_code_elimination$after_gvn (before)
263     /// CHECK:     If
264     /// CHECK:     Phi
265     /// CHECK:     If
266 
267     /// CHECK-START: int Main.$noinline$testEliminateIfParameterOppositeCondition_2(int, int, boolean) dead_code_elimination$after_gvn (after)
268     /// CHECK:     If
269     /// CHECK-NOT: If
$noinline$testEliminateIfParameterOppositeCondition_2( int a, int b, boolean condition)270     private static int $noinline$testEliminateIfParameterOppositeCondition_2(
271             int a, int b, boolean condition) {
272         int result = 0;
273         if (!condition) {
274             $noinline$emptyMethod(a + b);
275         } else {
276             $noinline$emptyMethod(a - b);
277         }
278         if (condition) {
279             result += $noinline$emptyMethod(a * 2);
280         } else {
281             result += $noinline$emptyMethod(b * 3);
282         }
283         return result;
284     }
285 
286     /// CHECK-START: int Main.$noinline$testEliminateIfFp(double, double) dead_code_elimination$after_gvn (before)
287     /// CHECK:     If
288     /// CHECK:     If
289 
290     /// CHECK-START: int Main.$noinline$testEliminateIfFp(double, double) dead_code_elimination$after_gvn (after)
291     /// CHECK:     If
292     /// CHECK-NOT: If
$noinline$testEliminateIfFp(double a, double b)293     private static int $noinline$testEliminateIfFp(double a, double b) {
294         int result = 0;
295         if (a < b) {
296             $noinline$emptyMethod(0);
297         } else {
298             $noinline$emptyMethod(1);
299         }
300         if (a < b) {
301             result += $noinline$emptyMethod(2);
302         } else {
303             result += $noinline$emptyMethod(3);
304         }
305         return result;
306     }
307 
308     /// CHECK-START: int Main.$noinline$testDoNotEliminateIfOppositeCondFpWrongBias(double, double) dead_code_elimination$initial (before)
309     /// CHECK:     If
310     /// CHECK:     If
311 
312     /// CHECK-START: int Main.$noinline$testDoNotEliminateIfOppositeCondFpWrongBias(double, double) dead_code_elimination$initial (after)
313     /// CHECK:     If
314     /// CHECK:     If
$noinline$testDoNotEliminateIfOppositeCondFpWrongBias(double a, double b)315     private static int $noinline$testDoNotEliminateIfOppositeCondFpWrongBias(double a, double b) {
316         int result = 0;
317         if (a < b) {
318             $noinline$emptyMethod(0);
319         } else {
320             $noinline$emptyMethod(1);
321         }
322         if (a >= b) {
323             result += $noinline$emptyMethod(2);
324         } else {
325             result += $noinline$emptyMethod(3);
326         }
327         return result;
328     }
329 
assertEquals(int expected, int result)330     public static void assertEquals(int expected, int result) {
331         if (expected != result) {
332             throw new Error("Expected: " + expected + ", found: " + result);
333         }
334     }
335 }
336