blob: 811c2804746bcaaa55aee9c12eea8e2e8181fd38 [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
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -070073 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (before)
Alexandre Rames9f980252016-02-05 14:00:28 +000074 /// CHECK: <<P1:z\d+>> ParameterValue
75 /// CHECK: <<P2:z\d+>> ParameterValue
76 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
77 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
78 /// CHECK: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
79 /// CHECK: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
80 /// CHECK: <<And:i\d+>> And [<<Select2>>,<<Select1>>]
81 /// CHECK: Return [<<And>>]
82
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -070083 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +000084 /// CHECK: <<Cond1:z\d+>> ParameterValue
85 /// CHECK: <<Cond2:z\d+>> ParameterValue
86 /// CHECK: <<Or:i\d+>> Or [<<Cond2>>,<<Cond1>>]
87 /// CHECK: <<BooleanNot:z\d+>> BooleanNot [<<Or>>]
88 /// CHECK: Return [<<BooleanNot>>]
89
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -070090 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +000091 /// CHECK: BooleanNot
92 /// CHECK-NOT: BooleanNot
93
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -070094 /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +000095 /// CHECK-NOT: And
96
97 public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
98 if (doThrow) throw new Error();
99 return !a & !b;
100 }
101
102 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000103 * Test transformation of Not/Not/Or into And/Not.
104 */
105
Alexandre Ramesa211a022016-02-04 13:16:08 +0000106 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000107 /// CHECK: <<P1:j\d+>> ParameterValue
108 /// CHECK: <<P2:j\d+>> ParameterValue
David Brazdilf02c3cf2016-02-29 09:14:51 +0000109 /// CHECK: <<Not1:j\d+>> Not [<<P1>>]
110 /// CHECK: <<Not2:j\d+>> Not [<<P2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000111 /// CHECK: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>]
112 /// CHECK: Return [<<Or>>]
113
Alexandre Ramesa211a022016-02-04 13:16:08 +0000114 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000115 /// CHECK: <<P1:j\d+>> ParameterValue
116 /// CHECK: <<P2:j\d+>> ParameterValue
117 /// CHECK: <<And:j\d+>> And [<<P1>>,<<P2>>]
118 /// CHECK: <<Not:j\d+>> Not [<<And>>]
119 /// CHECK: Return [<<Not>>]
120
Alexandre Ramesa211a022016-02-04 13:16:08 +0000121 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000122 /// CHECK: Not
123 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +0000124
125 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000126 /// CHECK-NOT: Or
127
128 public static long $opt$noinline$orToAnd(long a, long b) {
129 if (doThrow) throw new Error();
130 return ~a | ~b;
131 }
132
133 /**
Alexandre Rames9f980252016-02-05 14:00:28 +0000134 * Test transformation of Not/Not/Or into Or/And for boolean negations.
135 * Note that the graph before this instruction simplification pass does not
136 * contain `HBooleanNot` instructions. This is because this transformation
137 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
138 * same pass.
139 */
140
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700141 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (before)
Alexandre Rames9f980252016-02-05 14:00:28 +0000142 /// CHECK: <<P1:z\d+>> ParameterValue
143 /// CHECK: <<P2:z\d+>> ParameterValue
144 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
145 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
146 /// CHECK: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
147 /// CHECK: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
148 /// CHECK: <<Or:i\d+>> Or [<<Select2>>,<<Select1>>]
149 /// CHECK: Return [<<Or>>]
150
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700151 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000152 /// CHECK: <<Cond1:z\d+>> ParameterValue
153 /// CHECK: <<Cond2:z\d+>> ParameterValue
154 /// CHECK: <<And:i\d+>> And [<<Cond2>>,<<Cond1>>]
155 /// CHECK: <<BooleanNot:z\d+>> BooleanNot [<<And>>]
156 /// CHECK: Return [<<BooleanNot>>]
157
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700158 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000159 /// CHECK: BooleanNot
160 /// CHECK-NOT: BooleanNot
161
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700162 /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000163 /// CHECK-NOT: Or
164
165 public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
166 if (doThrow) throw new Error();
167 return !a | !b;
168 }
169
170 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000171 * Test that the transformation copes with inputs being separated from the
172 * bitwise operations.
173 * This is a regression test. The initial logic was inserting the new bitwise
174 * operation incorrectly.
175 */
176
Alexandre Ramesa211a022016-02-04 13:16:08 +0000177 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000178 /// CHECK: <<P1:i\d+>> ParameterValue
179 /// CHECK: <<P2:i\d+>> ParameterValue
David Brazdilf02c3cf2016-02-29 09:14:51 +0000180 /// CHECK: <<Cst1:i\d+>> IntConstant 1
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000181 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
David Brazdilf02c3cf2016-02-29 09:14:51 +0000182 /// CHECK: <<Not1:i\d+>> Not [<<AddP1>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000183 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
David Brazdilf02c3cf2016-02-29 09:14:51 +0000184 /// CHECK: <<Not2:i\d+>> Not [<<AddP2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000185 /// CHECK: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>]
186 /// CHECK: Return [<<Or>>]
187
Alexandre Ramesa211a022016-02-04 13:16:08 +0000188 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000189 /// CHECK: <<P1:i\d+>> ParameterValue
190 /// CHECK: <<P2:i\d+>> ParameterValue
191 /// CHECK: <<Cst1:i\d+>> IntConstant 1
192 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
193 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
194 /// CHECK: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>]
195 /// CHECK: <<Not:i\d+>> Not [<<And>>]
196 /// CHECK: Return [<<Not>>]
197
Alexandre Ramesa211a022016-02-04 13:16:08 +0000198 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000199 /// CHECK: Not
200 /// CHECK-NOT: Not
Alexandre Rames9f980252016-02-05 14:00:28 +0000201
202 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000203 /// CHECK-NOT: Or
204
205 public static int $opt$noinline$regressInputsAway(int a, int b) {
206 if (doThrow) throw new Error();
207 int a1 = a + 1;
208 int not_a1 = ~a1;
209 int b1 = b + 1;
210 int not_b1 = ~b1;
211 return not_a1 | not_b1;
212 }
213
214 /**
215 * Test transformation of Not/Not/Xor into Xor.
216 */
217
218 // See first note above.
Alexandre Ramesa211a022016-02-04 13:16:08 +0000219 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000220 /// CHECK: <<P1:i\d+>> ParameterValue
221 /// CHECK: <<P2:i\d+>> ParameterValue
David Brazdilf02c3cf2016-02-29 09:14:51 +0000222 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
223 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000224 /// CHECK: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>]
225 /// CHECK: Return [<<Xor>>]
226
Alexandre Ramesa211a022016-02-04 13:16:08 +0000227 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000228 /// CHECK: <<P1:i\d+>> ParameterValue
229 /// CHECK: <<P2:i\d+>> ParameterValue
230 /// CHECK: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>]
231 /// CHECK: Return [<<Xor>>]
232
Alexandre Ramesa211a022016-02-04 13:16:08 +0000233 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000234 /// CHECK-NOT: Not
235
236 public static int $opt$noinline$notXorToXor(int a, int b) {
237 if (doThrow) throw new Error();
238 return ~a ^ ~b;
239 }
240
241 /**
Alexandre Rames9f980252016-02-05 14:00:28 +0000242 * Test transformation of Not/Not/Xor into Xor for boolean negations.
243 * Note that the graph before this instruction simplification pass does not
244 * contain `HBooleanNot` instructions. This is because this transformation
245 * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
246 * same pass.
247 */
248
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700249 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (before)
Alexandre Rames9f980252016-02-05 14:00:28 +0000250 /// CHECK: <<P1:z\d+>> ParameterValue
251 /// CHECK: <<P2:z\d+>> ParameterValue
252 /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
253 /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
254 /// CHECK: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
255 /// CHECK: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
256 /// CHECK: <<Xor:i\d+>> Xor [<<Select2>>,<<Select1>>]
257 /// CHECK: Return [<<Xor>>]
258
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700259 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000260 /// CHECK: <<Cond1:z\d+>> ParameterValue
261 /// CHECK: <<Cond2:z\d+>> ParameterValue
262 /// CHECK: <<Xor:i\d+>> Xor [<<Cond2>>,<<Cond1>>]
263 /// CHECK: Return [<<Xor>>]
264
Wojciech Staszkiewicz5319d3c2016-08-01 17:48:59 -0700265 /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
Alexandre Rames9f980252016-02-05 14:00:28 +0000266 /// CHECK-NOT: BooleanNot
267
268 public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
269 if (doThrow) throw new Error();
270 return !a ^ !b;
271 }
272
273 /**
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000274 * Check that no transformation is done when one Not has multiple uses.
275 */
276
Alexandre Ramesa211a022016-02-04 13:16:08 +0000277 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000278 /// CHECK: <<P1:i\d+>> ParameterValue
279 /// CHECK: <<P2:i\d+>> ParameterValue
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000280 /// CHECK: <<One:i\d+>> IntConstant 1
David Brazdilf02c3cf2016-02-29 09:14:51 +0000281 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000282 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
David Brazdilf02c3cf2016-02-29 09:14:51 +0000283 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000284 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
285 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
286 /// CHECK: Return [<<Add>>]
287
Alexandre Ramesa211a022016-02-04 13:16:08 +0000288 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000289 /// CHECK: <<P1:i\d+>> ParameterValue
290 /// CHECK: <<P2:i\d+>> ParameterValue
291 /// CHECK: <<One:i\d+>> IntConstant 1
292 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
293 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
294 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
295 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
296 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
297 /// CHECK: Return [<<Add>>]
298
Alexandre Ramesa211a022016-02-04 13:16:08 +0000299 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000300 /// CHECK-NOT: Or
301
302 public static int $opt$noinline$notMultipleUses(int a, int b) {
303 if (doThrow) throw new Error();
304 int tmp = ~b;
305 return (tmp & 0x1) + (~a & tmp);
306 }
307
308 public static void main(String[] args) {
309 assertIntEquals(~0xff, $opt$noinline$andToOr(0xf, 0xff));
310 assertLongEquals(~0xf, $opt$noinline$orToAnd(0xf, 0xff));
311 assertIntEquals(0xf0, $opt$noinline$notXorToXor(0xf, 0xff));
312 assertIntEquals(~0xff, $opt$noinline$notMultipleUses(0xf, 0xff));
313 }
314}