blob: 2c759ed6f9ed560528f443760642167f387fcebb [file] [log] [blame]
Orion Hodson7d906302018-05-25 15:53:28 +01001/*
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
17import java.lang.reflect.Method;
18
19public class Main {
20
21 // Note #1: `javac` flips the conditions of If statements.
22 // Note #2: In the optimizing compiler, the first input of Phi is always
23 // the fall-through path, i.e. the false branch.
24
25 public static void assertBoolEquals(boolean expected, boolean result) {
26 if (expected != result) {
27 throw new Error("Expected: " + expected + ", found: " + result);
28 }
29 }
30
31 public static void assertIntEquals(int expected, int result) {
32 if (expected != result) {
33 throw new Error("Expected: " + expected + ", found: " + result);
34 }
35 }
36
37 /*
38 * Program which only delegates the condition, i.e. returns 1 when True
39 * and 0 when False.
40 */
41
42 /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (before)
43 /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
44 /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
45 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
46 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
47 /// CHECK-DAG: <<Cond:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
48 /// CHECK-DAG: If [<<Cond>>]
49 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0>>,<<Const1>>]
50 /// CHECK-DAG: Return [<<Phi>>]
51
52 /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (after)
53 /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
54 /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
55 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
56 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
57 /// CHECK-DAG: <<Cond:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
58 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const0>>,<<Const1>>,<<Cond>>]
59 /// CHECK-DAG: Return [<<Select>>]
60
61 public static boolean GreaterThan(int x, int y) {
62 return (x <= y) ? false : true;
63 }
64
65 /*
66 * Program which negates a condition, i.e. returns 0 when True
67 * and 1 when False.
68 */
69
70 /// CHECK-START: boolean Main.LessThan(int, int) select_generator (before)
71 /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
72 /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
73 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
74 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
75 /// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
76 /// CHECK-DAG: If [<<Cond>>]
77 /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
78 /// CHECK-DAG: Return [<<Phi>>]
79
80 /// CHECK-START: boolean Main.LessThan(int, int) select_generator (after)
81 /// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
82 /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
83 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
84 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
85 /// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
86 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>]
87 /// CHECK-DAG: Return [<<Select>>]
88
89 public static boolean LessThan(int x, int y) {
90 return (x < y) ? true : false;
91 }
92
93 /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
94 /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
95 /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
96 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
97 /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
98 /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const42>>]
99 /// CHECK-DAG: <<Select:i\d+>> Select [<<Const43>>,<<Add>>,<<ParamX>>]
100 /// CHECK-DAG: Return [<<Select>>]
101
102 /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
103 /// CHECK-NOT: If
104
105 public static int SimpleTrueBlock(boolean x, int y) {
106 return x ? y + 42 : 43;
107 }
108
109 /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
110 /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
111 /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
112 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
113 /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
114 /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const43>>]
115 /// CHECK-DAG: <<Select:i\d+>> Select [<<Add>>,<<Const42>>,<<ParamX>>]
116 /// CHECK-DAG: Return [<<Select>>]
117
118 /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
119 /// CHECK-NOT: If
120
121 public static int SimpleFalseBlock(boolean x, int y) {
122 return x ? 42 : y + 43;
123 }
124
125 /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
126 /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
127 /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
128 /// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
129 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
130 /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
131 /// CHECK-DAG: <<AddTrue:i\d+>> Add [<<ParamY>>,<<Const42>>]
132 /// CHECK-DAG: <<AddFalse:i\d+>> Add [<<ParamZ>>,<<Const43>>]
133 /// CHECK-DAG: <<Select:i\d+>> Select [<<AddFalse>>,<<AddTrue>>,<<ParamX>>]
134 /// CHECK-DAG: Return [<<Select>>]
135
136 /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
137 /// CHECK-NOT: If
138
139 public static int SimpleBothBlocks(boolean x, int y, int z) {
140 return x ? y + 42 : z + 43;
141 }
142
143 /// CHECK-START: int Main.ThreeBlocks(boolean, boolean) select_generator (after)
144 /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
145 /// CHECK-DAG: <<ParamY:z\d+>> ParameterValue
146 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
147 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
148 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
149 /// CHECK-DAG: <<Select23:i\d+>> Select [<<Const3>>,<<Const2>>,<<ParamY>>]
150 /// CHECK-DAG: <<Select123:i\d+>> Select [<<Select23>>,<<Const1>>,<<ParamX>>]
151 /// CHECK-DAG: Return [<<Select123>>]
152
153 public static int ThreeBlocks(boolean x, boolean y) {
154 if (x) {
155 return 1;
156 } else if (y) {
157 return 2;
158 } else {
159 return 3;
160 }
161 }
162
163 /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (before)
164 /// CHECK-DAG: <<This:l\d+>> ParameterValue
165 /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
166 /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
167 /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
168 /// CHECK-DAG: If [<<Cond>>]
169 /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
170 /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const2>>]
171 /// CHECK-DAG: Phi [<<Add>>,<<Const43>>]
172
173 /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (after)
174 /// CHECK-NOT: Select
175
176 public int TrueBlockWithTooManyInstructions(boolean x) {
177 return x ? (read_field + 2) : 43;
178 }
179
180 /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (before)
181 /// CHECK-DAG: <<This:l\d+>> ParameterValue
182 /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
183 /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
184 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
185 /// CHECK-DAG: If [<<Cond>>]
186 /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
187 /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const3>>]
188 /// CHECK-DAG: Phi [<<Const42>>,<<Add>>]
189
190 /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (after)
191 /// CHECK-NOT: Select
192
193 public int FalseBlockWithTooManyInstructions(boolean x) {
194 return x ? 42 : (read_field + 3);
195 }
196
197 /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (before)
198 /// CHECK-DAG: <<This:l\d+>> ParameterValue
199 /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
200 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
201 /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
202 /// CHECK-DAG: If [<<Cond>>]
203 /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const42>>]
204 /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
205
206 /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (after)
207 /// CHECK-NOT: Select
208
209 public int TrueBlockWithSideEffects(boolean x) {
210 return x ? (write_field = 42) : 43;
211 }
212
213 /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (before)
214 /// CHECK-DAG: <<This:l\d+>> ParameterValue
215 /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
216 /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
217 /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
218 /// CHECK-DAG: If [<<Cond>>]
219 /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const43>>]
220 /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
221
222 /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (after)
223 /// CHECK-NOT: Select
224
225 public int FalseBlockWithSideEffects(boolean x) {
226 return x ? 42 : (write_field = 43);
227 }
228
229 public static void main(String[] args) throws Exception {
230 Class main2 = Class.forName("Main2");
231 Method booleanNot = main2.getMethod("BooleanNot", boolean.class);
232 Method valuesOrdered = main2.getMethod("ValuesOrdered", int.class, int.class, int.class);
233 Method negatedCondition = main2.getMethod("NegatedCondition", boolean.class);
234 Method multiplePhis = main2.getMethod("MultiplePhis");
235
236 assertBoolEquals(false, (boolean)booleanNot.invoke(null, true));
237 assertBoolEquals(true, (boolean)booleanNot.invoke(null, false));
238 assertBoolEquals(true, GreaterThan(10, 5));
239 assertBoolEquals(false, GreaterThan(10, 10));
240 assertBoolEquals(false, GreaterThan(5, 10));
241 assertBoolEquals(true, LessThan(5, 10));
242 assertBoolEquals(false, LessThan(10, 10));
243 assertBoolEquals(false, LessThan(10, 5));
244
245 assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 1, 3, 5));
246 assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 5, 3, 1));
247 assertBoolEquals(false, (boolean)valuesOrdered.invoke(null, 1, 3, 2));
248 assertBoolEquals(false, (boolean)valuesOrdered.invoke(null, 2, 3, 1));
249 assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 3, 3, 3));
250 assertBoolEquals(true, (boolean)valuesOrdered.invoke(null, 3, 3, 5));
251 assertBoolEquals(false, (boolean)valuesOrdered.invoke(null, 5, 5, 3));
252 assertIntEquals(42, (int)negatedCondition.invoke(null, true));
253 assertIntEquals(43, (int)negatedCondition.invoke(null, false));
254 assertIntEquals(46, SimpleTrueBlock(true, 4));
255 assertIntEquals(43, SimpleTrueBlock(false, 4));
256 assertIntEquals(42, SimpleFalseBlock(true, 7));
257 assertIntEquals(50, SimpleFalseBlock(false, 7));
258 assertIntEquals(48, SimpleBothBlocks(true, 6, 2));
259 assertIntEquals(45, SimpleBothBlocks(false, 6, 2));
260 assertIntEquals(1, ThreeBlocks(true, true));
261 assertIntEquals(1, ThreeBlocks(true, false));
262 assertIntEquals(2, ThreeBlocks(false, true));
263 assertIntEquals(3, ThreeBlocks(false, false));
264 assertIntEquals(13, (int)multiplePhis.invoke(null));
265
266 Main m = new Main();
267 assertIntEquals(42, m.TrueBlockWithTooManyInstructions(true));
268 assertIntEquals(43, m.TrueBlockWithTooManyInstructions(false));
269 assertIntEquals(42, m.FalseBlockWithTooManyInstructions(true));
270 assertIntEquals(43, m.FalseBlockWithTooManyInstructions(false));
271 assertIntEquals(42, m.TrueBlockWithSideEffects(true));
272 assertIntEquals(43, m.TrueBlockWithSideEffects(false));
273 assertIntEquals(42, m.FalseBlockWithSideEffects(true));
274 assertIntEquals(43, m.FalseBlockWithSideEffects(false));
275 }
276
277 // These need to be instance fields so as to not generate a LoadClass for iget/iput.
278 public int read_field = 40;
279 public int write_field = 42;
280}