blob: 5ccc648076ee599b2b2cf7020b767936db85109e [file] [log] [blame]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +00001/*
Roland Levillainfb7fc7b2016-02-24 15:41:20 +00002 * 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 */
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000016
17public class Main {
18
19 // A dummy value to defeat inlining of these routines.
20 static boolean doThrow = false;
21
22 public static void assertIntEquals(int expected, int result) {
23 if (expected != result) {
24 throw new Error("Expected: " + expected + ", found: " + result);
25 }
26 }
27
28 public static void assertLongEquals(long expected, long result) {
29 if (expected != result) {
30 throw new Error("Expected: " + expected + ", found: " + result);
31 }
32 }
33
34 /**
35 * Test transformation of Not/Not/And into Or/Not.
36 */
37
Alexandre Ramesa211a022016-02-04 13:16:08 +000038 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000039 /// CHECK: <<P1:i\d+>> ParameterValue
40 /// CHECK: <<P2:i\d+>> ParameterValue
David Brazdilf02c3cf2016-02-29 09:14:51 +000041 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
42 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000043 /// CHECK: <<And:i\d+>> And [<<Not1>>,<<Not2>>]
44 /// CHECK: Return [<<And>>]
45
Alexandre Ramesa211a022016-02-04 13:16:08 +000046 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000047 /// CHECK: <<P1:i\d+>> ParameterValue
48 /// CHECK: <<P2:i\d+>> ParameterValue
49 /// CHECK: <<Or:i\d+>> Or [<<P1>>,<<P2>>]
50 /// CHECK: <<Not:i\d+>> Not [<<Or>>]
51 /// CHECK: Return [<<Not>>]
52
Alexandre Ramesa211a022016-02-04 13:16:08 +000053 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000054 /// CHECK: Not
55 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +000056
57 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000058 /// CHECK-NOT: And
59
60 public static int $opt$noinline$andToOr(int a, int b) {
61 if (doThrow) throw new Error();
62 return ~a & ~b;
63 }
64
65 /**
Alexandre Rames9f980252016-02-05 14:00:28 +000066 * Test transformation of Not/Not/And into Or/Not for boolean negations.
67 * Note that the graph before this instruction simplification pass does not
68 * contain `HBooleanNot` instructions. This is because this transformation
69 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
70 * same pass.
71 */
72
Sebastien Hertz9837caf2016-08-01 11:09:50 +020073 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (before)
Alexandre Rames9f980252016-02-05 14:00:28 +000074 /// CHECK: <<P1:z\d+>> ParameterValue
75 /// CHECK: <<P2:z\d+>> ParameterValue
Alexandre Rames9f980252016-02-05 14:00:28 +000076 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
Sebastien Hertz9837caf2016-08-01 11:09:50 +020077 /// CHECK-DAG: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>]
78 /// CHECK-DAG: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>]
79 /// CHECK: <<And:i\d+>> And [<<NotP1>>,<<NotP2>>]
Alexandre Rames9f980252016-02-05 14:00:28 +000080 /// CHECK: Return [<<And>>]
81
Sebastien Hertz9837caf2016-08-01 11:09:50 +020082 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (after)
Alexandre Rames9f980252016-02-05 14:00:28 +000083 /// CHECK: <<Cond1:z\d+>> ParameterValue
84 /// CHECK: <<Cond2:z\d+>> ParameterValue
Sebastien Hertz9837caf2016-08-01 11:09:50 +020085 /// CHECK: <<Or:i\d+>> Or [<<Cond1>>,<<Cond2>>]
Alexandre Rames9f980252016-02-05 14:00:28 +000086 /// CHECK: <<BooleanNot:z\d+>> BooleanNot [<<Or>>]
87 /// CHECK: Return [<<BooleanNot>>]
88
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -070089 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +000090 /// CHECK: BooleanNot
91 /// CHECK-NOT: BooleanNot
92
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -070093 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +000094 /// CHECK-NOT: And
95
96 public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
97 if (doThrow) throw new Error();
98 return !a & !b;
99 }
100
101 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000102 * Test transformation of Not/Not/Or into And/Not.
103 */
104
Alexandre Ramesa211a022016-02-04 13:16:08 +0000105 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000106 /// CHECK: <<P1:j\d+>> ParameterValue
107 /// CHECK: <<P2:j\d+>> ParameterValue
David Brazdilf02c3cf2016-02-29 09:14:51 +0000108 /// CHECK: <<Not1:j\d+>> Not [<<P1>>]
109 /// CHECK: <<Not2:j\d+>> Not [<<P2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000110 /// CHECK: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>]
111 /// CHECK: Return [<<Or>>]
112
Alexandre Ramesa211a022016-02-04 13:16:08 +0000113 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000114 /// CHECK: <<P1:j\d+>> ParameterValue
115 /// CHECK: <<P2:j\d+>> ParameterValue
116 /// CHECK: <<And:j\d+>> And [<<P1>>,<<P2>>]
117 /// CHECK: <<Not:j\d+>> Not [<<And>>]
118 /// CHECK: Return [<<Not>>]
119
Alexandre Ramesa211a022016-02-04 13:16:08 +0000120 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000121 /// CHECK: Not
122 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +0000123
124 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000125 /// CHECK-NOT: Or
126
127 public static long $opt$noinline$orToAnd(long a, long b) {
128 if (doThrow) throw new Error();
129 return ~a | ~b;
130 }
131
132 /**
Alexandre Rames9f980252016-02-05 14:00:28 +0000133 * Test transformation of Not/Not/Or into Or/And for boolean negations.
134 * Note that the graph before this instruction simplification pass does not
135 * contain `HBooleanNot` instructions. This is because this transformation
136 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
137 * same pass.
138 */
139
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200140 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (before)
Alexandre Rames9f980252016-02-05 14:00:28 +0000141 /// CHECK: <<P1:z\d+>> ParameterValue
142 /// CHECK: <<P2:z\d+>> ParameterValue
Alexandre Rames9f980252016-02-05 14:00:28 +0000143 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200144 /// CHECK: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>]
145 /// CHECK: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>]
146 /// CHECK: <<Or:i\d+>> Or [<<NotP1>>,<<NotP2>>]
Alexandre Rames9f980252016-02-05 14:00:28 +0000147 /// CHECK: Return [<<Or>>]
148
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200149 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000150 /// CHECK: <<Cond1:z\d+>> ParameterValue
151 /// CHECK: <<Cond2:z\d+>> ParameterValue
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200152 /// CHECK: <<And:i\d+>> And [<<Cond1>>,<<Cond2>>]
Alexandre Rames9f980252016-02-05 14:00:28 +0000153 /// CHECK: <<BooleanNot:z\d+>> BooleanNot [<<And>>]
154 /// CHECK: Return [<<BooleanNot>>]
155
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700156 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000157 /// CHECK: BooleanNot
158 /// CHECK-NOT: BooleanNot
159
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700160 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000161 /// CHECK-NOT: Or
162
163 public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
164 if (doThrow) throw new Error();
165 return !a | !b;
166 }
167
168 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000169 * Test that the transformation copes with inputs being separated from the
170 * bitwise operations.
171 * This is a regression test. The initial logic was inserting the new bitwise
172 * operation incorrectly.
173 */
174
Alexandre Ramesa211a022016-02-04 13:16:08 +0000175 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000176 /// CHECK: <<P1:i\d+>> ParameterValue
177 /// CHECK: <<P2:i\d+>> ParameterValue
David Brazdilf02c3cf2016-02-29 09:14:51 +0000178 /// CHECK: <<Cst1:i\d+>> IntConstant 1
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000179 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
David Brazdilf02c3cf2016-02-29 09:14:51 +0000180 /// CHECK: <<Not1:i\d+>> Not [<<AddP1>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000181 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
David Brazdilf02c3cf2016-02-29 09:14:51 +0000182 /// CHECK: <<Not2:i\d+>> Not [<<AddP2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000183 /// CHECK: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>]
184 /// CHECK: Return [<<Or>>]
185
Alexandre Ramesa211a022016-02-04 13:16:08 +0000186 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000187 /// CHECK: <<P1:i\d+>> ParameterValue
188 /// CHECK: <<P2:i\d+>> ParameterValue
189 /// CHECK: <<Cst1:i\d+>> IntConstant 1
190 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
191 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
192 /// CHECK: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>]
193 /// CHECK: <<Not:i\d+>> Not [<<And>>]
194 /// CHECK: Return [<<Not>>]
195
Alexandre Ramesa211a022016-02-04 13:16:08 +0000196 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000197 /// CHECK: Not
198 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +0000199
200 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000201 /// CHECK-NOT: Or
202
203 public static int $opt$noinline$regressInputsAway(int a, int b) {
204 if (doThrow) throw new Error();
205 int a1 = a + 1;
206 int not_a1 = ~a1;
207 int b1 = b + 1;
208 int not_b1 = ~b1;
209 return not_a1 | not_b1;
210 }
211
212 /**
213 * Test transformation of Not/Not/Xor into Xor.
214 */
215
216 // See first note above.
Alexandre Ramesa211a022016-02-04 13:16:08 +0000217 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000218 /// CHECK: <<P1:i\d+>> ParameterValue
219 /// CHECK: <<P2:i\d+>> ParameterValue
David Brazdilf02c3cf2016-02-29 09:14:51 +0000220 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
221 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000222 /// CHECK: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>]
223 /// CHECK: Return [<<Xor>>]
224
Alexandre Ramesa211a022016-02-04 13:16:08 +0000225 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000226 /// CHECK: <<P1:i\d+>> ParameterValue
227 /// CHECK: <<P2:i\d+>> ParameterValue
228 /// CHECK: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>]
229 /// CHECK: Return [<<Xor>>]
230
Alexandre Ramesa211a022016-02-04 13:16:08 +0000231 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000232 /// CHECK-NOT: Not
233
234 public static int $opt$noinline$notXorToXor(int a, int b) {
235 if (doThrow) throw new Error();
236 return ~a ^ ~b;
237 }
238
239 /**
Alexandre Rames9f980252016-02-05 14:00:28 +0000240 * Test transformation of Not/Not/Xor into Xor for boolean negations.
241 * Note that the graph before this instruction simplification pass does not
242 * contain `HBooleanNot` instructions. This is because this transformation
243 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
244 * same pass.
245 */
246
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200247 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (before)
Alexandre Rames9f980252016-02-05 14:00:28 +0000248 /// CHECK: <<P1:z\d+>> ParameterValue
249 /// CHECK: <<P2:z\d+>> ParameterValue
Alexandre Rames9f980252016-02-05 14:00:28 +0000250 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200251 /// CHECK: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>]
252 /// CHECK: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>]
253 /// CHECK: <<Xor:i\d+>> Xor [<<NotP1>>,<<NotP2>>]
Alexandre Rames9f980252016-02-05 14:00:28 +0000254 /// CHECK: Return [<<Xor>>]
255
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200256 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000257 /// CHECK: <<Cond1:z\d+>> ParameterValue
258 /// CHECK: <<Cond2:z\d+>> ParameterValue
Sebastien Hertz9837caf2016-08-01 11:09:50 +0200259 /// CHECK: <<Xor:i\d+>> Xor [<<Cond1>>,<<Cond2>>]
Alexandre Rames9f980252016-02-05 14:00:28 +0000260 /// CHECK: Return [<<Xor>>]
261
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700262 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000263 /// CHECK-NOT: BooleanNot
264
265 public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
266 if (doThrow) throw new Error();
267 return !a ^ !b;
268 }
269
270 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000271 * Check that no transformation is done when one Not has multiple uses.
272 */
273
Alexandre Ramesa211a022016-02-04 13:16:08 +0000274 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000275 /// CHECK: <<P1:i\d+>> ParameterValue
276 /// CHECK: <<P2:i\d+>> ParameterValue
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000277 /// CHECK: <<One:i\d+>> IntConstant 1
David Brazdilf02c3cf2016-02-29 09:14:51 +0000278 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000279 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
David Brazdilf02c3cf2016-02-29 09:14:51 +0000280 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000281 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
282 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
283 /// CHECK: Return [<<Add>>]
284
Alexandre Ramesa211a022016-02-04 13:16:08 +0000285 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000286 /// CHECK: <<P1:i\d+>> ParameterValue
287 /// CHECK: <<P2:i\d+>> ParameterValue
288 /// CHECK: <<One:i\d+>> IntConstant 1
289 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
290 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
291 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
292 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
293 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
294 /// CHECK: Return [<<Add>>]
295
Alexandre Ramesa211a022016-02-04 13:16:08 +0000296 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000297 /// CHECK-NOT: Or
298
299 public static int $opt$noinline$notMultipleUses(int a, int b) {
300 if (doThrow) throw new Error();
301 int tmp = ~b;
302 return (tmp & 0x1) + (~a & tmp);
303 }
304
305 public static void main(String[] args) {
306 assertIntEquals(~0xff, $opt$noinline$andToOr(0xf, 0xff));
307 assertLongEquals(~0xf, $opt$noinline$orToAnd(0xf, 0xff));
308 assertIntEquals(0xf0, $opt$noinline$notXorToXor(0xf, 0xff));
309 assertIntEquals(~0xff, $opt$noinline$notMultipleUses(0xf, 0xff));
310 }
311}