Main.java revision fb7fc7b1e11523b6e4f444f0f54de0b49cd0c4e1
1/*
2 * 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 */
16
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
38  // Note: before the instruction_simplifier pass, Xor's are used instead of
39  // Not's (the simplification happens during the same pass).
40  /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
41  /// CHECK:       <<P1:i\d+>>          ParameterValue
42  /// CHECK:       <<P2:i\d+>>          ParameterValue
43  /// CHECK:       <<CstM1:i\d+>>       IntConstant -1
44  /// CHECK:       <<Not1:i\d+>>        Xor [<<P1>>,<<CstM1>>]
45  /// CHECK:       <<Not2:i\d+>>        Xor [<<P2>>,<<CstM1>>]
46  /// CHECK:       <<And:i\d+>>         And [<<Not1>>,<<Not2>>]
47  /// CHECK:                            Return [<<And>>]
48
49  /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
50  /// CHECK:       <<P1:i\d+>>          ParameterValue
51  /// CHECK:       <<P2:i\d+>>          ParameterValue
52  /// CHECK:       <<Or:i\d+>>          Or [<<P1>>,<<P2>>]
53  /// CHECK:       <<Not:i\d+>>         Not [<<Or>>]
54  /// CHECK:                            Return [<<Not>>]
55
56  /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
57  /// CHECK:                            Not
58  /// CHECK-NOT:                        Not
59
60  /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
61  /// CHECK-NOT:                        And
62
63  public static int $opt$noinline$andToOr(int a, int b) {
64    if (doThrow) throw new Error();
65    return ~a & ~b;
66  }
67
68  /**
69   * Test transformation of Not/Not/And into Or/Not for boolean negations.
70   * Note that the graph before this instruction simplification pass does not
71   * contain `HBooleanNot` instructions. This is because this transformation
72   * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
73   * same pass.
74   */
75
76  /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (before)
77  /// CHECK:       <<P1:z\d+>>          ParameterValue
78  /// CHECK:       <<P2:z\d+>>          ParameterValue
79  /// CHECK-DAG:   <<Const0:i\d+>>      IntConstant 0
80  /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
81  /// CHECK:       <<Select1:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P1>>]
82  /// CHECK:       <<Select2:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P2>>]
83  /// CHECK:       <<And:i\d+>>         And [<<Select2>>,<<Select1>>]
84  /// CHECK:                            Return [<<And>>]
85
86  /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (after)
87  /// CHECK:       <<Cond1:z\d+>>       ParameterValue
88  /// CHECK:       <<Cond2:z\d+>>       ParameterValue
89  /// CHECK:       <<Or:i\d+>>          Or [<<Cond2>>,<<Cond1>>]
90  /// CHECK:       <<BooleanNot:z\d+>>  BooleanNot [<<Or>>]
91  /// CHECK:                            Return [<<BooleanNot>>]
92
93  /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (after)
94  /// CHECK:                            BooleanNot
95  /// CHECK-NOT:                        BooleanNot
96
97  /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier_after_bce (after)
98  /// CHECK-NOT:                        And
99
100  public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
101    if (doThrow) throw new Error();
102    return !a & !b;
103  }
104
105  /**
106   * Test transformation of Not/Not/Or into And/Not.
107   */
108
109  // See note above.
110  // The second Xor has its arguments reversed for no obvious reason.
111  /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
112  /// CHECK:       <<P1:j\d+>>          ParameterValue
113  /// CHECK:       <<P2:j\d+>>          ParameterValue
114  /// CHECK:       <<CstM1:j\d+>>       LongConstant -1
115  /// CHECK:       <<Not1:j\d+>>        Xor [<<P1>>,<<CstM1>>]
116  /// CHECK:       <<Not2:j\d+>>        Xor [<<CstM1>>,<<P2>>]
117  /// CHECK:       <<Or:j\d+>>          Or [<<Not1>>,<<Not2>>]
118  /// CHECK:                            Return [<<Or>>]
119
120  /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
121  /// CHECK:       <<P1:j\d+>>          ParameterValue
122  /// CHECK:       <<P2:j\d+>>          ParameterValue
123  /// CHECK:       <<And:j\d+>>         And [<<P1>>,<<P2>>]
124  /// CHECK:       <<Not:j\d+>>         Not [<<And>>]
125  /// CHECK:                            Return [<<Not>>]
126
127  /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
128  /// CHECK:                            Not
129  /// CHECK-NOT:                        Not
130
131  /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
132  /// CHECK-NOT:                        Or
133
134  public static long $opt$noinline$orToAnd(long a, long b) {
135    if (doThrow) throw new Error();
136    return ~a | ~b;
137  }
138
139  /**
140   * Test transformation of Not/Not/Or into Or/And for boolean negations.
141   * Note that the graph before this instruction simplification pass does not
142   * contain `HBooleanNot` instructions. This is because this transformation
143   * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
144   * same pass.
145   */
146
147  /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (before)
148  /// CHECK:       <<P1:z\d+>>          ParameterValue
149  /// CHECK:       <<P2:z\d+>>          ParameterValue
150  /// CHECK-DAG:   <<Const0:i\d+>>      IntConstant 0
151  /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
152  /// CHECK:       <<Select1:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P1>>]
153  /// CHECK:       <<Select2:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P2>>]
154  /// CHECK:       <<Or:i\d+>>          Or [<<Select2>>,<<Select1>>]
155  /// CHECK:                            Return [<<Or>>]
156
157  /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (after)
158  /// CHECK:       <<Cond1:z\d+>>       ParameterValue
159  /// CHECK:       <<Cond2:z\d+>>       ParameterValue
160  /// CHECK:       <<And:i\d+>>         And [<<Cond2>>,<<Cond1>>]
161  /// CHECK:       <<BooleanNot:z\d+>>  BooleanNot [<<And>>]
162  /// CHECK:                            Return [<<BooleanNot>>]
163
164  /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (after)
165  /// CHECK:                            BooleanNot
166  /// CHECK-NOT:                        BooleanNot
167
168  /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier_after_bce (after)
169  /// CHECK-NOT:                        Or
170
171  public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
172    if (doThrow) throw new Error();
173    return !a | !b;
174  }
175
176  /**
177   * Test that the transformation copes with inputs being separated from the
178   * bitwise operations.
179   * This is a regression test. The initial logic was inserting the new bitwise
180   * operation incorrectly.
181   */
182
183  /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
184  /// CHECK:       <<P1:i\d+>>          ParameterValue
185  /// CHECK:       <<P2:i\d+>>          ParameterValue
186  /// CHECK-DAG:   <<Cst1:i\d+>>        IntConstant 1
187  /// CHECK-DAG:   <<CstM1:i\d+>>       IntConstant -1
188  /// CHECK:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
189  /// CHECK:       <<Not1:i\d+>>        Xor [<<AddP1>>,<<CstM1>>]
190  /// CHECK:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
191  /// CHECK:       <<Not2:i\d+>>        Xor [<<AddP2>>,<<CstM1>>]
192  /// CHECK:       <<Or:i\d+>>          Or [<<Not1>>,<<Not2>>]
193  /// CHECK:                            Return [<<Or>>]
194
195  /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
196  /// CHECK:       <<P1:i\d+>>          ParameterValue
197  /// CHECK:       <<P2:i\d+>>          ParameterValue
198  /// CHECK:       <<Cst1:i\d+>>        IntConstant 1
199  /// CHECK:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
200  /// CHECK:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
201  /// CHECK:       <<And:i\d+>>         And [<<AddP1>>,<<AddP2>>]
202  /// CHECK:       <<Not:i\d+>>         Not [<<And>>]
203  /// CHECK:                            Return [<<Not>>]
204
205  /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
206  /// CHECK:                            Not
207  /// CHECK-NOT:                        Not
208
209  /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
210  /// CHECK-NOT:                        Or
211
212  public static int $opt$noinline$regressInputsAway(int a, int b) {
213    if (doThrow) throw new Error();
214    int a1 = a + 1;
215    int not_a1 = ~a1;
216    int b1 = b + 1;
217    int not_b1 = ~b1;
218    return not_a1 | not_b1;
219  }
220
221  /**
222   * Test transformation of Not/Not/Xor into Xor.
223   */
224
225  // See first note above.
226  /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
227  /// CHECK:       <<P1:i\d+>>          ParameterValue
228  /// CHECK:       <<P2:i\d+>>          ParameterValue
229  /// CHECK:       <<CstM1:i\d+>>       IntConstant -1
230  /// CHECK:       <<Not1:i\d+>>        Xor [<<P1>>,<<CstM1>>]
231  /// CHECK:       <<Not2:i\d+>>        Xor [<<P2>>,<<CstM1>>]
232  /// CHECK:       <<Xor:i\d+>>         Xor [<<Not1>>,<<Not2>>]
233  /// CHECK:                            Return [<<Xor>>]
234
235  /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
236  /// CHECK:       <<P1:i\d+>>          ParameterValue
237  /// CHECK:       <<P2:i\d+>>          ParameterValue
238  /// CHECK:       <<Xor:i\d+>>         Xor [<<P1>>,<<P2>>]
239  /// CHECK:                            Return [<<Xor>>]
240
241  /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
242  /// CHECK-NOT:                        Not
243
244  public static int $opt$noinline$notXorToXor(int a, int b) {
245    if (doThrow) throw new Error();
246    return ~a ^ ~b;
247  }
248
249  /**
250   * Test transformation of Not/Not/Xor into Xor for boolean negations.
251   * Note that the graph before this instruction simplification pass does not
252   * contain `HBooleanNot` instructions. This is because this transformation
253   * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
254   * same pass.
255   */
256
257  /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier_after_bce (before)
258  /// CHECK:       <<P1:z\d+>>          ParameterValue
259  /// CHECK:       <<P2:z\d+>>          ParameterValue
260  /// CHECK-DAG:   <<Const0:i\d+>>      IntConstant 0
261  /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
262  /// CHECK:       <<Select1:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P1>>]
263  /// CHECK:       <<Select2:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P2>>]
264  /// CHECK:       <<Xor:i\d+>>         Xor [<<Select2>>,<<Select1>>]
265  /// CHECK:                            Return [<<Xor>>]
266
267  /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier_after_bce (after)
268  /// CHECK:       <<Cond1:z\d+>>       ParameterValue
269  /// CHECK:       <<Cond2:z\d+>>       ParameterValue
270  /// CHECK:       <<Xor:i\d+>>         Xor [<<Cond2>>,<<Cond1>>]
271  /// CHECK:                            Return [<<Xor>>]
272
273  /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier_after_bce (after)
274  /// CHECK-NOT:                        BooleanNot
275
276  public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
277    if (doThrow) throw new Error();
278    return !a ^ !b;
279  }
280
281  /**
282   * Check that no transformation is done when one Not has multiple uses.
283   */
284
285  /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
286  /// CHECK:       <<P1:i\d+>>          ParameterValue
287  /// CHECK:       <<P2:i\d+>>          ParameterValue
288  /// CHECK:       <<CstM1:i\d+>>       IntConstant -1
289  /// CHECK:       <<One:i\d+>>         IntConstant 1
290  /// CHECK:       <<Not2:i\d+>>        Xor [<<P2>>,<<CstM1>>]
291  /// CHECK:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
292  /// CHECK:       <<Not1:i\d+>>        Xor [<<P1>>,<<CstM1>>]
293  /// CHECK:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
294  /// CHECK:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
295  /// CHECK:                            Return [<<Add>>]
296
297  /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
298  /// CHECK:       <<P1:i\d+>>          ParameterValue
299  /// CHECK:       <<P2:i\d+>>          ParameterValue
300  /// CHECK:       <<One:i\d+>>         IntConstant 1
301  /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
302  /// CHECK:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
303  /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
304  /// CHECK:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
305  /// CHECK:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
306  /// CHECK:                            Return [<<Add>>]
307
308  /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
309  /// CHECK-NOT:                        Or
310
311  public static int $opt$noinline$notMultipleUses(int a, int b) {
312    if (doThrow) throw new Error();
313    int tmp = ~b;
314    return (tmp & 0x1) + (~a & tmp);
315  }
316
317  public static void main(String[] args) {
318    assertIntEquals(~0xff, $opt$noinline$andToOr(0xf, 0xff));
319    assertLongEquals(~0xf, $opt$noinline$orToAnd(0xf, 0xff));
320    assertIntEquals(0xf0, $opt$noinline$notXorToXor(0xf, 0xff));
321    assertIntEquals(~0xff, $opt$noinline$notMultipleUses(0xf, 0xff));
322  }
323}
324