1 /*
2 * Copyright (C) 2014 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 
assertIntEquals(int expected, int result)19   public static void assertIntEquals(int expected, int result) {
20     if (expected != result) {
21       throw new Error("Expected: " + expected + ", found: " + result);
22     }
23   }
24 
assertLongEquals(long expected, long result)25   public static void assertLongEquals(long expected, long result) {
26     if (expected != result) {
27       throw new Error("Expected: " + expected + ", found: " + result);
28     }
29   }
30 
31   /**
32    * Tiny three-register program exercising int constant folding
33    * on negation.
34    */
35 
36   // CHECK-START: int Main.IntNegation() constant_folding (before)
37   // CHECK-DAG:     [[Const42:i\d+]]  IntConstant 42
38   // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Const42]] ]
39   // CHECK-DAG:                       Return [ [[Neg]] ]
40 
41   // CHECK-START: int Main.IntNegation() constant_folding (after)
42   // CHECK-DAG:     [[ConstN42:i\d+]] IntConstant -42
43   // CHECK-DAG:                       Return [ [[ConstN42]] ]
44 
IntNegation()45   public static int IntNegation() {
46     int x, y;
47     x = 42;
48     y = -x;
49     return y;
50   }
51 
52   /**
53    * Tiny three-register program exercising int constant folding
54    * on addition.
55    */
56 
57   // CHECK-START: int Main.IntAddition1() constant_folding (before)
58   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
59   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
60   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const1]] [[Const2]] ]
61   // CHECK-DAG:                      Return [ [[Add]] ]
62 
63   // CHECK-START: int Main.IntAddition1() constant_folding (after)
64   // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
65   // CHECK-DAG:                      Return [ [[Const3]] ]
66 
IntAddition1()67   public static int IntAddition1() {
68     int a, b, c;
69     a = 1;
70     b = 2;
71     c = a + b;
72     return c;
73   }
74 
75  /**
76   * Small three-register program exercising int constant folding
77   * on addition.
78   */
79 
80   // CHECK-START: int Main.IntAddition2() constant_folding (before)
81   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
82   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
83   // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
84   // CHECK-DAG:     [[Const6:i\d+]]  IntConstant 6
85   // CHECK-DAG:     [[Add1:i\d+]]    Add [ [[Const1]] [[Const2]] ]
86   // CHECK-DAG:     [[Add2:i\d+]]    Add [ [[Const5]] [[Const6]] ]
87   // CHECK-DAG:     [[Add3:i\d+]]    Add [ [[Add1]] [[Add2]] ]
88   // CHECK-DAG:                      Return [ [[Add3]] ]
89 
90   // CHECK-START: int Main.IntAddition2() constant_folding (after)
91   // CHECK-DAG:     [[Const14:i\d+]] IntConstant 14
92   // CHECK-DAG:                      Return [ [[Const14]] ]
93 
IntAddition2()94   public static int IntAddition2() {
95     int a, b, c;
96     a = 1;
97     b = 2;
98     a += b;
99     b = 5;
100     c = 6;
101     b += c;
102     c = a + b;
103     return c;
104   }
105 
106   /**
107    * Tiny three-register program exercising int constant folding
108    * on subtraction.
109    */
110 
111   // CHECK-START: int Main.IntSubtraction() constant_folding (before)
112   // CHECK-DAG:     [[Const6:i\d+]]  IntConstant 6
113   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
114   // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const6]] [[Const2]] ]
115   // CHECK-DAG:                      Return [ [[Sub]] ]
116 
117   // CHECK-START: int Main.IntSubtraction() constant_folding (after)
118   // CHECK-DAG:     [[Const4:i\d+]]  IntConstant 4
119   // CHECK-DAG:                      Return [ [[Const4]] ]
120 
IntSubtraction()121   public static int IntSubtraction() {
122     int a, b, c;
123     a = 6;
124     b = 2;
125     c = a - b;
126     return c;
127   }
128 
129   /**
130    * Tiny three-register program exercising long constant folding
131    * on addition.
132    */
133 
134   // CHECK-START: long Main.LongAddition() constant_folding (before)
135   // CHECK-DAG:     [[Const1:j\d+]]  LongConstant 1
136   // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
137   // CHECK-DAG:     [[Add:j\d+]]     Add [ [[Const1]] [[Const2]] ]
138   // CHECK-DAG:                      Return [ [[Add]] ]
139 
140   // CHECK-START: long Main.LongAddition() constant_folding (after)
141   // CHECK-DAG:     [[Const3:j\d+]]  LongConstant 3
142   // CHECK-DAG:                      Return [ [[Const3]] ]
143 
LongAddition()144   public static long LongAddition() {
145     long a, b, c;
146     a = 1L;
147     b = 2L;
148     c = a + b;
149     return c;
150   }
151 
152   /**
153    * Tiny three-register program exercising long constant folding
154    * on subtraction.
155    */
156 
157   // CHECK-START: long Main.LongSubtraction() constant_folding (before)
158   // CHECK-DAG:     [[Const6:j\d+]]  LongConstant 6
159   // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
160   // CHECK-DAG:     [[Sub:j\d+]]     Sub [ [[Const6]] [[Const2]] ]
161   // CHECK-DAG:                      Return [ [[Sub]] ]
162 
163   // CHECK-START: long Main.LongSubtraction() constant_folding (after)
164   // CHECK-DAG:     [[Const4:j\d+]]  LongConstant 4
165   // CHECK-DAG:                      Return [ [[Const4]] ]
166 
LongSubtraction()167   public static long LongSubtraction() {
168     long a, b, c;
169     a = 6L;
170     b = 2L;
171     c = a - b;
172     return c;
173   }
174 
175   /**
176    * Three-register program with a constant (static) condition.
177    */
178 
179   // CHECK-START: int Main.StaticCondition() constant_folding (before)
180   // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
181   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
182   // CHECK-DAG:     [[Cond:z\d+]]    GreaterThanOrEqual [ [[Const7]] [[Const2]] ]
183   // CHECK-DAG:                      If [ [[Cond]] ]
184 
185   // CHECK-START: int Main.StaticCondition() constant_folding (after)
186   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
187   // CHECK-DAG:                      If [ [[Const1]] ]
188 
StaticCondition()189   public static int StaticCondition() {
190     int a, b, c;
191     a = 7;
192     b = 2;
193     if (a < b)
194       c = a + b;
195     else
196       c = a - b;
197     return c;
198   }
199 
200   /**
201    * Four-variable program with jumps leading to the creation of many
202    * blocks.
203    *
204    * The intent of this test is to ensure that all constant expressions
205    * are actually evaluated at compile-time, thanks to the reverse
206    * (forward) post-order traversal of the the dominator tree.
207    */
208 
209   // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before)
210   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
211   // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
212   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const5]] [[Const2]] ]
213   // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const5]] [[Const2]] ]
214   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
215   // CHECK-DAG:                      Return [ [[Phi]] ]
216 
217   // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
218   // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
219   // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
220   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Const7]] [[Const3]] ]
221   // CHECK-DAG:                      Return [ [[Phi]] ]
222 
JumpsAndConditionals(boolean cond)223   public static int JumpsAndConditionals(boolean cond) {
224     int a, b, c;
225     a = 5;
226     b = 2;
227     if (cond)
228       c = a + b;
229     else
230       c = a - b;
231     return c;
232   }
233 
234   /**
235    * Test optimizations of arithmetic identities yielding a constant result.
236    */
237 
238   // CHECK-START: int Main.And0(int) constant_folding (before)
239   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
240   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
241   // CHECK-DAG:     [[And:i\d+]]      And [ [[Arg]] [[Const0]] ]
242   // CHECK-DAG:                       Return [ [[And]] ]
243 
244   // CHECK-START: int Main.And0(int) constant_folding (after)
245   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
246   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
247   // CHECK-NOT:                       And
248   // CHECK-DAG:                       Return [ [[Const0]] ]
249 
And0(int arg)250   public static int And0(int arg) {
251     return arg & 0;
252   }
253 
254   // CHECK-START: long Main.Mul0(long) constant_folding (before)
255   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
256   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
257   // CHECK-DAG:     [[Mul:j\d+]]      Mul [ [[Arg]] [[Const0]] ]
258   // CHECK-DAG:                       Return [ [[Mul]] ]
259 
260   // CHECK-START: long Main.Mul0(long) constant_folding (after)
261   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
262   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
263   // CHECK-NOT:                       Mul
264   // CHECK-DAG:                       Return [ [[Const0]] ]
265 
Mul0(long arg)266   public static long Mul0(long arg) {
267     return arg * 0;
268   }
269 
270   // CHECK-START: int Main.OrAllOnes(int) constant_folding (before)
271   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
272   // CHECK-DAG:     [[ConstF:i\d+]]   IntConstant -1
273   // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Arg]] [[ConstF]] ]
274   // CHECK-DAG:                       Return [ [[Or]] ]
275 
276   // CHECK-START: int Main.OrAllOnes(int) constant_folding (after)
277   // CHECK-DAG:     [[ConstF:i\d+]]   IntConstant -1
278   // CHECK-NOT:                       Or
279   // CHECK-DAG:                       Return [ [[ConstF]] ]
280 
OrAllOnes(int arg)281   public static int OrAllOnes(int arg) {
282     return arg | -1;
283   }
284 
285   // CHECK-START: long Main.Rem0(long) constant_folding (before)
286   // CHECK-DAG:     [[Arg:j\d+]]           ParameterValue
287   // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
288   // CHECK-DAG:     [[DivZeroCheck:j\d+]]  DivZeroCheck [ [[Arg]] ]
289   // CHECK-DAG:     [[Rem:j\d+]]           Rem [ [[Const0]] [[DivZeroCheck]] ]
290   // CHECK-DAG:                            Return [ [[Rem]] ]
291 
292   // CHECK-START: long Main.Rem0(long) constant_folding (after)
293   // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
294   // CHECK-NOT:                            Rem
295   // CHECK-DAG:                            Return [ [[Const0]] ]
296 
Rem0(long arg)297   public static long Rem0(long arg) {
298     return 0 % arg;
299   }
300 
301   // CHECK-START: int Main.Rem1(int) constant_folding (before)
302   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
303   // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
304   // CHECK-DAG:     [[Rem:i\d+]]      Rem [ [[Arg]] [[Const1]] ]
305   // CHECK-DAG:                       Return [ [[Rem]] ]
306 
307   // CHECK-START: int Main.Rem1(int) constant_folding (after)
308   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
309   // CHECK-NOT:                       Rem
310   // CHECK-DAG:                       Return [ [[Const0]] ]
311 
Rem1(int arg)312   public static int Rem1(int arg) {
313     return arg % 1;
314   }
315 
316   // CHECK-START: long Main.RemN1(long) constant_folding (before)
317   // CHECK-DAG:     [[Arg:j\d+]]           ParameterValue
318   // CHECK-DAG:     [[ConstN1:j\d+]]       LongConstant -1
319   // CHECK-DAG:     [[DivZeroCheck:j\d+]]  DivZeroCheck [ [[Arg]] ]
320   // CHECK-DAG:     [[Rem:j\d+]]           Rem [ [[Arg]] [[DivZeroCheck]] ]
321   // CHECK-DAG:                            Return [ [[Rem]] ]
322 
323   // CHECK-START: long Main.RemN1(long) constant_folding (after)
324   // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
325   // CHECK-NOT:                            Rem
326   // CHECK-DAG:                            Return [ [[Const0]] ]
327 
RemN1(long arg)328   public static long RemN1(long arg) {
329     return arg % -1;
330   }
331 
332   // CHECK-START: int Main.Shl0(int) constant_folding (before)
333   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
334   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
335   // CHECK-DAG:     [[Shl:i\d+]]      Shl [ [[Const0]] [[Arg]] ]
336   // CHECK-DAG:                       Return [ [[Shl]] ]
337 
338   // CHECK-START: int Main.Shl0(int) constant_folding (after)
339   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
340   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
341   // CHECK-NOT:                       Shl
342   // CHECK-DAG:                       Return [ [[Const0]] ]
343 
Shl0(int arg)344   public static int Shl0(int arg) {
345     return 0 << arg;
346   }
347 
348   // CHECK-START: long Main.Shr0(int) constant_folding (before)
349   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
350   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
351   // CHECK-DAG:     [[Shr:j\d+]]      Shr [ [[Const0]] [[Arg]] ]
352   // CHECK-DAG:                       Return [ [[Shr]] ]
353 
354   // CHECK-START: long Main.Shr0(int) constant_folding (after)
355   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
356   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
357   // CHECK-NOT:                       Shr
358   // CHECK-DAG:                       Return [ [[Const0]] ]
359 
Shr0(int arg)360   public static long Shr0(int arg) {
361     return (long)0 >> arg;
362   }
363 
364   // CHECK-START: long Main.SubSameLong(long) constant_folding (before)
365   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
366   // CHECK-DAG:     [[Sub:j\d+]]      Sub [ [[Arg]] [[Arg]] ]
367   // CHECK-DAG:                       Return [ [[Sub]] ]
368 
369   // CHECK-START: long Main.SubSameLong(long) constant_folding (after)
370   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
371   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
372   // CHECK-NOT:                       Sub
373   // CHECK-DAG:                       Return [ [[Const0]] ]
374 
SubSameLong(long arg)375   public static long SubSameLong(long arg) {
376     return arg - arg;
377   }
378 
379   // CHECK-START: int Main.UShr0(int) constant_folding (before)
380   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
381   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
382   // CHECK-DAG:     [[UShr:i\d+]]     UShr [ [[Const0]] [[Arg]] ]
383   // CHECK-DAG:                       Return [ [[UShr]] ]
384 
385   // CHECK-START: int Main.UShr0(int) constant_folding (after)
386   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
387   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
388   // CHECK-NOT:                       UShr
389   // CHECK-DAG:                       Return [ [[Const0]] ]
390 
UShr0(int arg)391   public static int UShr0(int arg) {
392     return 0 >>> arg;
393   }
394 
395   // CHECK-START: int Main.XorSameInt(int) constant_folding (before)
396   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
397   // CHECK-DAG:     [[Xor:i\d+]]      Xor [ [[Arg]] [[Arg]] ]
398   // CHECK-DAG:                       Return [ [[Xor]] ]
399 
400   // CHECK-START: int Main.XorSameInt(int) constant_folding (after)
401   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
402   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
403   // CHECK-NOT:                       Xor
404   // CHECK-DAG:                       Return [ [[Const0]] ]
405 
XorSameInt(int arg)406   public static int XorSameInt(int arg) {
407     return arg ^ arg;
408   }
409 
main(String[] args)410   public static void main(String[] args) {
411     assertIntEquals(IntNegation(), -42);
412     assertIntEquals(IntAddition1(), 3);
413     assertIntEquals(IntAddition2(), 14);
414     assertIntEquals(IntSubtraction(), 4);
415     assertLongEquals(LongAddition(), 3L);
416     assertLongEquals(LongSubtraction(), 4L);
417     assertIntEquals(StaticCondition(), 5);
418     assertIntEquals(JumpsAndConditionals(true), 7);
419     assertIntEquals(JumpsAndConditionals(false), 3);
420     int random = 123456;  // Chosen randomly.
421     assertIntEquals(And0(random), 0);
422     assertLongEquals(Mul0(random), 0);
423     assertIntEquals(OrAllOnes(random), -1);
424     assertLongEquals(Rem0(random), 0);
425     assertIntEquals(Rem1(random), 0);
426     assertLongEquals(RemN1(random), 0);
427     assertIntEquals(Shl0(random), 0);
428     assertLongEquals(Shr0(random), 0);
429     assertLongEquals(SubSameLong(random), 0);
430     assertIntEquals(UShr0(random), 0);
431     assertIntEquals(XorSameInt(random), 0);
432   }
433 }
434