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 
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 
inlineTrue()25   public static boolean inlineTrue() {
26     return true;
27   }
28 
inlineFalse()29   public static boolean inlineFalse() {
30     return false;
31   }
32 
33   // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (before)
34   // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
35   // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
36   // CHECK-DAG:                      If
37   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[ArgX]] [[ArgY]] ]
38   // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[ArgX]] [[ArgY]] ]
39   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
40   // CHECK-DAG:                      Return [ [[Phi]] ]
41 
42   // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
43   // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
44   // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
45   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[ArgX]] [[ArgY]] ]
46   // CHECK-DAG:                      Return [ [[Add]] ]
47 
48   // CHECK-START: int Main.testTrueBranch(int, int) dead_code_elimination_final (after)
49   // CHECK-NOT:                      If
50   // CHECK-NOT:                      Sub
51   // CHECK-NOT:                      Phi
52 
testTrueBranch(int x, int y)53   public static int testTrueBranch(int x, int y) {
54     int z;
55     if (inlineTrue()) {
56       z = x + y;
57     } else {
58       z = x - y;
59     }
60     return z;
61   }
62 
63   // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (before)
64   // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
65   // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
66   // CHECK-DAG:                      If
67   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[ArgX]] [[ArgY]] ]
68   // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[ArgX]] [[ArgY]] ]
69   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
70   // CHECK-DAG:                      Return [ [[Phi]] ]
71 
72   // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
73   // CHECK-DAG:     [[ArgX:i\d+]]    ParameterValue
74   // CHECK-DAG:     [[ArgY:i\d+]]    ParameterValue
75   // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[ArgX]] [[ArgY]] ]
76   // CHECK-DAG:                      Return [ [[Sub]] ]
77 
78   // CHECK-START: int Main.testFalseBranch(int, int) dead_code_elimination_final (after)
79   // CHECK-NOT:                      If
80   // CHECK-NOT:                      Add
81   // CHECK-NOT:                      Phi
82 
testFalseBranch(int x, int y)83   public static int testFalseBranch(int x, int y) {
84     int z;
85     if (inlineFalse()) {
86       z = x + y;
87     } else {
88       z = x - y;
89     }
90     return z;
91   }
92 
93   // CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination_final (before)
94   // CHECK:                          Mul
95 
96   // CHECK-START: int Main.testRemoveLoop(int) dead_code_elimination_final (after)
97   // CHECK-NOT:                      Mul
98 
testRemoveLoop(int x)99   public static int testRemoveLoop(int x) {
100     if (inlineFalse()) {
101       for (int i = 0; i < x; ++i) {
102         x *= x;
103       }
104     }
105     return x;
106   }
107 
108   // CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination_final (before)
109   // CHECK-DAG:                      Return
110   // CHECK-DAG:                      Exit
111 
112   // CHECK-START: int Main.testInfiniteLoop(int) dead_code_elimination_final (after)
113   // CHECK-NOT:                      Return
114   // CHECK-NOT:                      Exit
115 
testInfiniteLoop(int x)116   public static int testInfiniteLoop(int x) {
117     while (inlineTrue()) {
118       x++;
119     }
120     return x;
121   }
122 
123   // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (before)
124   // CHECK-DAG:                      If
125   // CHECK-DAG:                      Add
126 
127   // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
128   // CHECK-DAG:     [[Arg:i\d+]]     ParameterValue
129   // CHECK-DAG:                      Return [ [[Arg]] ]
130 
131   // CHECK-START: int Main.testDeadLoop(int) dead_code_elimination_final (after)
132   // CHECK-NOT:                      If
133   // CHECK-NOT:                      Add
134 
testDeadLoop(int x)135   public static int testDeadLoop(int x) {
136     while (inlineFalse()) {
137       x++;
138     }
139     return x;
140   }
141 
142   // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (before)
143   // CHECK-DAG:                      If
144   // CHECK-DAG:                      If
145   // CHECK-DAG:                      Add
146 
147   // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
148   // CHECK-DAG:     [[Arg:i\d+]]     ParameterValue
149   // CHECK-DAG:                      Return [ [[Arg]] ]
150 
151   // CHECK-START: int Main.testUpdateLoopInformation(int) dead_code_elimination_final (after)
152   // CHECK-NOT:                      If
153   // CHECK-NOT:                      Add
154 
testUpdateLoopInformation(int x)155   public static int testUpdateLoopInformation(int x) {
156     // Use of Or in the condition generates a dead loop where not all of its
157     // blocks are removed. This forces DCE to update their loop information.
158     while (inlineFalse() || !inlineTrue()) {
159       x++;
160     }
161     return x;
162   }
163 
164   // CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination_final (before)
165   // CHECK:                          SuspendCheck
166   // CHECK:                          SuspendCheck
167   // CHECK:                          SuspendCheck
168   // CHECK-NOT:                      SuspendCheck
169 
170   // CHECK-START: int Main.testRemoveSuspendCheck(int, int) dead_code_elimination_final (after)
171   // CHECK:                          SuspendCheck
172   // CHECK:                          SuspendCheck
173   // CHECK-NOT:                      SuspendCheck
174 
testRemoveSuspendCheck(int x, int y)175   public static int testRemoveSuspendCheck(int x, int y) {
176     // Inner loop will leave behind the header with its SuspendCheck. DCE must
177     // remove it, otherwise the outer loop would end up with two.
178     while (y > 0) {
179       while (inlineFalse() || !inlineTrue()) {
180         x++;
181       }
182       y--;
183     }
184     return x;
185   }
186 
main(String[] args)187   public static void main(String[] args) {
188     assertIntEquals(7, testTrueBranch(4, 3));
189     assertIntEquals(1, testFalseBranch(4, 3));
190     assertIntEquals(42, testRemoveLoop(42));
191     assertIntEquals(23, testUpdateLoopInformation(23));
192     assertIntEquals(12, testRemoveSuspendCheck(12, 5));
193   }
194 }
195