1 /*
2  * Copyright (C) 2015 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 import java.lang.reflect.Method;
17 
18 public class Main {
19 
assertIntEquals(int expected, int result)20   public static void assertIntEquals(int expected, int result) {
21     if (expected != result) {
22       throw new Error("Expected: " + expected + ", found: " + result);
23     }
24   }
25 
inlineTrue()26   public static boolean inlineTrue() {
27     return true;
28   }
29 
inlineFalse()30   public static boolean inlineFalse() {
31     return false;
32   }
33 
testTrueBranch(int x, int y)34   public static int testTrueBranch(int x, int y) {
35       try {
36       Class<?> c = Class.forName("Smali");
37       Method m = c.getMethod("testTrueBranch", int.class, int.class);
38       return (Integer) m.invoke(null, x, y);
39     } catch (Throwable t) {
40       throw new RuntimeException(t);
41     }
42   }
43 
testFalseBranch(int x, int y)44   public static int testFalseBranch(int x, int y) {
45       try {
46       Class<?> c = Class.forName("Smali");
47       Method m = c.getMethod("testFalseBranch", int.class, int.class);
48       return (Integer) m.invoke(null, x, y);
49     } catch (Throwable t) {
50       throw new RuntimeException(t);
51     }
52   }
53 
54   /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination$after_inlining (before)
55   /// CHECK:                          Mul
56 
57   /// CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination$after_inlining (after)
58   /// CHECK-NOT:                      Mul
59 
testRemoveLoop(int x)60   public static int testRemoveLoop(int x) {
61     if (inlineFalse()) {
62       for (int i = 0; i < x; ++i) {
63         x *= x;
64       }
65     }
66     return x;
67   }
68 
69   /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination$after_inlining (before)
70   /// CHECK-DAG:                      Return
71   /// CHECK-DAG:                      Exit
72 
73   /// CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination$after_inlining (after)
74   /// CHECK-NOT:                      Return
75   /// CHECK-NOT:                      Exit
76 
testInfiniteLoop(int x)77   public static int testInfiniteLoop(int x) {
78     while (inlineTrue()) {
79       x++;
80     }
81     return x;
82   }
83 
84   /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (before)
85   /// CHECK-DAG:                      If
86   /// CHECK-DAG:                      Add
87 
88   /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (after)
89   /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
90   /// CHECK-DAG:                      Return [<<Arg>>]
91 
92   /// CHECK-START: int Main.testDeadLoop(int) dead_code_elimination$after_inlining (after)
93   /// CHECK-NOT:                      If
94   /// CHECK-NOT:                      Add
95 
testDeadLoop(int x)96   public static int testDeadLoop(int x) {
97     while (inlineFalse()) {
98       x++;
99     }
100     return x;
101   }
102 
103   /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (before)
104   /// CHECK-DAG:                      If
105   /// CHECK-DAG:                      If
106   /// CHECK-DAG:                      Add
107 
108   /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (after)
109   /// CHECK-DAG:     <<Arg:i\d+>>     ParameterValue
110   /// CHECK-DAG:                      Return [<<Arg>>]
111 
112   /// CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination$after_inlining (after)
113   /// CHECK-NOT:                      If
114   /// CHECK-NOT:                      Add
115 
testUpdateLoopInformation(int x)116   public static int testUpdateLoopInformation(int x) {
117     // Use of Or in the condition generates a dead loop where not all of its
118     // blocks are removed. This forces DCE to update their loop information.
119     while (inlineFalse() || !inlineTrue()) {
120       x++;
121     }
122     return x;
123   }
124 
125   /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination$after_inlining (before)
126   /// CHECK:                          SuspendCheck
127   /// CHECK:                          SuspendCheck
128   /// CHECK:                          SuspendCheck
129   /// CHECK-NOT:                      SuspendCheck
130 
131   /// CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination$after_inlining (after)
132   /// CHECK:                          SuspendCheck
133   /// CHECK:                          SuspendCheck
134   /// CHECK-NOT:                      SuspendCheck
135 
testRemoveSuspendCheck(int x, int y)136   public static int testRemoveSuspendCheck(int x, int y) {
137     // Inner loop will leave behind the header with its SuspendCheck. DCE must
138     // remove it, otherwise the outer loop would end up with two.
139     while (y > 0) {
140       while (inlineFalse() || !inlineTrue()) {
141         x++;
142       }
143       y--;
144     }
145     return x;
146   }
147 
main(String[] args)148   public static void main(String[] args) {
149     assertIntEquals(7, testTrueBranch(4, 3));
150     assertIntEquals(1, testFalseBranch(4, 3));
151     assertIntEquals(42, testRemoveLoop(42));
152     assertIntEquals(23, testUpdateLoopInformation(23));
153     assertIntEquals(12, testRemoveSuspendCheck(12, 5));
154   }
155 }
156