1 /*
2  * Copyright (C) 2016 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 
main(String[] args)19   public static void main(String[] args) {
20     testNoInline(args);
21     System.out.println(staticField);
22     testInline(args);
23     System.out.println(staticField);
24     testNonConstantInputs(args);
25     System.out.println(staticField);
26     testNonConstantEqual(args);
27     System.out.println(staticField);
28     testGreaterCondition(args);
29     System.out.println(staticField);
30     testSwitch(args);
31     System.out.println(staticField);
32     testFP(args);
33     System.out.println(staticField);
34   }
35 
36   // Test when a condition is the input of the if.
37 
38   /// CHECK-START: void Main.testNoInline(java.lang.String[]) dead_code_elimination$initial (before)
39   /// CHECK: <<Const0:i\d+>>   IntConstant 0
40   /// CHECK:                   If
41   /// CHECK: <<Phi:i\d+>>      Phi
42   /// CHECK: <<Equal:z\d+>>    Equal [<<Phi>>,<<Const0>>]
43   /// CHECK:                   If [<<Equal>>]
44 
45   /// CHECK-START: void Main.testNoInline(java.lang.String[]) dead_code_elimination$initial (after)
46   /// CHECK:      If
47   /// CHECK-NOT:  Phi
48   /// CHECK-NOT:  Equal
49   /// CHECK-NOT:  If
testNoInline(String[] args)50   public static void testNoInline(String[] args) {
51     boolean myVar = false;
52     if (args.length == 42) {
53       myVar = true;
54     } else {
55       staticField = 32;
56       myVar = false;
57     }
58     if (myVar) {
59       staticField = 12;
60     } else {
61       staticField = 54;
62     }
63   }
64 
65   // Test when the phi is the input of the if.
66 
67   /// CHECK-START: void Main.testInline(java.lang.String[]) dead_code_elimination$after_inlining (before)
68   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0
69   /// CHECK-DAG:                   If
70   /// CHECK-DAG: <<Phi:i\d+>>      Phi
71   /// CHECK-DAG:                   If [<<Phi>>]
72 
73   /// CHECK-START: void Main.testInline(java.lang.String[]) dead_code_elimination$after_inlining (after)
74   /// CHECK:      If
75   /// CHECK-NOT:  Phi
76   /// CHECK-NOT:  If
testInline(String[] args)77   public static void testInline(String[] args) {
78     boolean myVar = $inline$doTest(args);
79     if (myVar) {
80       staticField = 12;
81     } else {
82       staticField = 54;
83     }
84   }
85 
$inline$doTest(String[] args)86   public static boolean $inline$doTest(String[] args) {
87     boolean myVar;
88     if (args.length == 42) {
89       myVar = true;
90     } else {
91       staticField = 32;
92       myVar = false;
93     }
94     return myVar;
95   }
96 
97   // Test when one input is not a constant. We can only optimize the constant input.
98 
99   /// CHECK-START: void Main.testNonConstantInputs(java.lang.String[]) dead_code_elimination$initial (before)
100   /// CHECK-DAG: <<Const34:i\d+>>         IntConstant 34
101   /// CHECK-DAG: <<Const42:i\d+>>         IntConstant 42
102   /// CHECK-DAG:                          If
103   /// CHECK-DAG: <<StaticFieldGet:i\d+>>  StaticFieldGet
104   /// CHECK-DAG: <<Phi:i\d+>>             Phi [<<Const34>>,<<StaticFieldGet>>]
105   /// CHECK-DAG: <<NotEqual:z\d+>>        NotEqual [<<Phi>>,<<Const42>>]
106   /// CHECK-DAG:                          If [<<NotEqual>>]
107 
108   /// CHECK-START: void Main.testNonConstantInputs(java.lang.String[]) dead_code_elimination$initial (after)
109   /// CHECK-DAG: <<Const42:i\d+>>         IntConstant 42
110   /// CHECK-DAG:                          If
111   /// CHECK-DAG: <<StaticFieldGet:i\d+>>  StaticFieldGet
112   /// CHECK-NOT:                          Phi
113   /// CHECK-DAG: <<NotEqual:z\d+>>        NotEqual [<<StaticFieldGet>>,<<Const42>>]
114   /// CHECK-DAG:                          If [<<NotEqual>>]
testNonConstantInputs(String[] args)115   public static void testNonConstantInputs(String[] args) {
116     int a = 42;
117     if (args.length == 42) {
118       a = 34;
119     } else {
120       staticField = 32;
121       a = otherStaticField;
122     }
123     if (a == 42) {
124       staticField = 12;
125     } else {
126       staticField = 54;
127     }
128   }
129 
130   // Test with a condition.
131 
132   /// CHECK-START: void Main.testGreaterCondition(java.lang.String[]) dead_code_elimination$initial (before)
133   /// CHECK-DAG: <<Const34:i\d+>>         IntConstant 34
134   /// CHECK-DAG: <<Const22:i\d+>>         IntConstant 22
135   /// CHECK-DAG: <<Const25:i\d+>>         IntConstant 25
136   /// CHECK-DAG:                          If
137   /// CHECK-DAG: <<Phi:i\d+>>             Phi [<<Const34>>,<<Const22>>]
138   /// CHECK-DAG: <<GE:z\d+>>              GreaterThanOrEqual [<<Phi>>,<<Const25>>]
139   /// CHECK-DAG:                          If [<<GE>>]
140 
141   /// CHECK-START: void Main.testGreaterCondition(java.lang.String[]) dead_code_elimination$initial (after)
142   /// CHECK-DAG:                          If
143   /// CHECK-NOT:                          Phi
144   /// CHECK-NOT:                          GreaterThanOrEqual
145   /// CHECK-NOT:                          If
testGreaterCondition(String[] args)146   public static void testGreaterCondition(String[] args) {
147     int a = 42;
148     if (args.length == 42) {
149       a = 34;
150     } else {
151       staticField = 32;
152       a = 22;
153     }
154     if (a < 25) {
155       staticField = 12;
156     } else {
157       staticField = 54;
158     }
159   }
160 
161   // Test when comparing non constants.
162 
163   /// CHECK-START: void Main.testNonConstantEqual(java.lang.String[]) dead_code_elimination$initial (before)
164   /// CHECK-DAG: <<Const34:i\d+>>         IntConstant 34
165   /// CHECK-DAG: <<Const42:i\d+>>         IntConstant 42
166   /// CHECK-DAG:                          If
167   /// CHECK-DAG: <<StaticFieldGet:i\d+>>  StaticFieldGet
168   /// CHECK-DAG: <<Phi:i\d+>>             Phi [<<Const34>>,<<StaticFieldGet>>]
169   /// CHECK-DAG: <<NotEqual:z\d+>>        NotEqual [<<Phi>>,<<StaticFieldGet>>]
170   /// CHECK-DAG:                          If [<<NotEqual>>]
171 
172   /// CHECK-START: void Main.testNonConstantEqual(java.lang.String[]) dead_code_elimination$initial (after)
173   /// CHECK-DAG: <<Const34:i\d+>>         IntConstant 34
174   /// CHECK-DAG:                          If
175   /// CHECK-DAG: <<StaticFieldGet:i\d+>>  StaticFieldGet
176   /// CHECK-NOT:                          Phi
177   /// CHECK-DAG: <<NotEqual:z\d+>>        NotEqual [<<Const34>>,<<StaticFieldGet>>]
178   /// CHECK-DAG:                          If [<<NotEqual>>]
testNonConstantEqual(String[] args)179   public static void testNonConstantEqual(String[] args) {
180     int a = 42;
181     int b = otherStaticField;
182     if (args.length == 42) {
183       a = 34;
184     } else {
185       staticField = 32;
186       a = b;
187     }
188     if (a == b) {
189       staticField = 12;
190     } else {
191       staticField = 54;
192     }
193   }
194 
195   // Make sure we don't "simplify" a loop and potentially turn it into
196   // an irreducible loop. The suspend check at the loop header prevents
197   // us from doing the simplification.
198 
199   /// CHECK-START: void Main.testLoop(boolean) disassembly (after)
200   /// CHECK-DAG: SuspendCheck
201   /// CHECK:     irreducible:false
202   /// CHECK-NOT: irreducible:true
testLoop(boolean c)203   public static void testLoop(boolean c) {
204     while (true) {
205       if (c) {
206         if ($noinline$foo()) return;
207         c = false;
208       } else {
209         $noinline$foo();
210         c = true;
211       }
212     }
213   }
214 
$noinline$foo()215   static boolean $noinline$foo() {
216     if (doThrow) throw new Error("");
217     return true;
218   }
219 
220   /// CHECK-START: void Main.testSwitch(java.lang.String[]) dead_code_elimination$initial (before)
221   /// CHECK:      If
222   /// CHECK:      If
223   /// CHECK:      If
224 
225   /// CHECK-START: void Main.testSwitch(java.lang.String[]) dead_code_elimination$initial (after)
226   /// CHECK:      If
227   /// CHECK:      If
228   /// CHECK-NOT:  If
testSwitch(String[] args)229   public static void testSwitch(String[] args) {
230     boolean cond = false;
231     switch (args.length) {
232       case 42:
233         staticField = 11;
234         cond = true;
235         break;
236       case 43:
237         staticField = 33;
238         cond = true;
239         break;
240       default:
241         cond = false;
242         break;
243     }
244     if (cond) {
245       // Redirect case 42 and 43 here.
246       staticField = 2;
247     }
248     // Redirect default here.
249   }
250 
251   /// CHECK-START: void Main.testFP(java.lang.String[]) dead_code_elimination$initial (before)
252   /// CHECK:      If
253   /// CHECK:      If
254 
255   /// CHECK-START: void Main.testFP(java.lang.String[]) dead_code_elimination$initial (after)
256   /// CHECK:      If
257   /// CHECK:      If
testFP(String[] args)258   public static void testFP(String[] args) {
259     float f = 2.2f;
260     float nan = $noinline$getNaN();
261     if (args.length == 42) {
262       f = 4.3f;
263     } else {
264       staticField = 33;
265       f = nan;
266     }
267     if (f == nan) {
268       staticField = 5;
269     }
270   }
271 
272   // No inline variant to avoid having the compiler see it's a NaN.
$noinline$getNaN()273   static float $noinline$getNaN() {
274     if (doThrow) throw new Error("");
275     return Float.NaN;
276   }
277 
278   static boolean doThrow;
279   static int staticField;
280   static int otherStaticField;
281 }
282