• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 public class Main {
18 
19   // A dummy value to defeat inlining of these routines.
20   static boolean doThrow = false;
21 
assertIntEquals(int expected, int result)22   public static void assertIntEquals(int expected, int result) {
23     if (expected != result) {
24       throw new Error("Expected: " + expected + ", found: " + result);
25     }
26   }
27 
assertLongEquals(long expected, long result)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   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
39   /// CHECK:       <<P1:i\d+>>          ParameterValue
40   /// CHECK:       <<P2:i\d+>>          ParameterValue
41   /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
42   /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
43   /// CHECK:       <<And:i\d+>>         And [<<Not1>>,<<Not2>>]
44   /// CHECK:                            Return [<<And>>]
45 
46   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
47   /// 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 
53   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
54   /// CHECK:                            Not
55   /// CHECK-NOT:                        Not
56 
57   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
58   /// CHECK-NOT:                        And
59 
$opt$noinline$andToOr(int a, int b)60   public static int $opt$noinline$andToOr(int a, int b) {
61     if (doThrow) throw new Error();
62     return ~a & ~b;
63   }
64 
65   /**
66    * 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 
73   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (before)
74   /// CHECK:       <<P1:z\d+>>          ParameterValue
75   /// CHECK:       <<P2:z\d+>>          ParameterValue
76   /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
77   /// 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>>]
80   /// CHECK:                            Return [<<And>>]
81 
82   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (after)
83   /// CHECK:       <<Cond1:z\d+>>       ParameterValue
84   /// CHECK:       <<Cond2:z\d+>>       ParameterValue
85   /// CHECK:       <<Or:i\d+>>          Or [<<Cond1>>,<<Cond2>>]
86   /// CHECK:       <<BooleanNot:z\d+>>  BooleanNot [<<Or>>]
87   /// CHECK:                            Return [<<BooleanNot>>]
88 
89   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
90   /// CHECK:                            BooleanNot
91   /// CHECK-NOT:                        BooleanNot
92 
93   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
94   /// CHECK-NOT:                        And
95 
$opt$noinline$booleanAndToOr(boolean a, boolean b)96   public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
97     if (doThrow) throw new Error();
98     return !a & !b;
99   }
100 
101   /**
102    * Test transformation of Not/Not/Or into And/Not.
103    */
104 
105   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
106   /// CHECK:       <<P1:j\d+>>          ParameterValue
107   /// CHECK:       <<P2:j\d+>>          ParameterValue
108   /// CHECK:       <<Not1:j\d+>>        Not [<<P1>>]
109   /// CHECK:       <<Not2:j\d+>>        Not [<<P2>>]
110   /// CHECK:       <<Or:j\d+>>          Or [<<Not1>>,<<Not2>>]
111   /// CHECK:                            Return [<<Or>>]
112 
113   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
114   /// 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 
120   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
121   /// CHECK:                            Not
122   /// CHECK-NOT:                        Not
123 
124   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
125   /// CHECK-NOT:                        Or
126 
$opt$noinline$orToAnd(long a, long b)127   public static long $opt$noinline$orToAnd(long a, long b) {
128     if (doThrow) throw new Error();
129     return ~a | ~b;
130   }
131 
132   /**
133    * 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 
140   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (before)
141   /// CHECK:       <<P1:z\d+>>          ParameterValue
142   /// CHECK:       <<P2:z\d+>>          ParameterValue
143   /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
144   /// CHECK:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
145   /// CHECK:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
146   /// CHECK:       <<Or:i\d+>>          Or [<<NotP1>>,<<NotP2>>]
147   /// CHECK:                            Return [<<Or>>]
148 
149   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (after)
150   /// CHECK:       <<Cond1:z\d+>>       ParameterValue
151   /// CHECK:       <<Cond2:z\d+>>       ParameterValue
152   /// CHECK:       <<And:i\d+>>         And [<<Cond1>>,<<Cond2>>]
153   /// CHECK:       <<BooleanNot:z\d+>>  BooleanNot [<<And>>]
154   /// CHECK:                            Return [<<BooleanNot>>]
155 
156   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
157   /// CHECK:                            BooleanNot
158   /// CHECK-NOT:                        BooleanNot
159 
160   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
161   /// CHECK-NOT:                        Or
162 
$opt$noinline$booleanOrToAnd(boolean a, boolean b)163   public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
164     if (doThrow) throw new Error();
165     return !a | !b;
166   }
167 
168   /**
169    * 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 
175   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
176   /// CHECK:       <<P1:i\d+>>          ParameterValue
177   /// CHECK:       <<P2:i\d+>>          ParameterValue
178   /// CHECK:       <<Cst1:i\d+>>        IntConstant 1
179   /// CHECK:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
180   /// CHECK:       <<Not1:i\d+>>        Not [<<AddP1>>]
181   /// CHECK:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
182   /// CHECK:       <<Not2:i\d+>>        Not [<<AddP2>>]
183   /// CHECK:       <<Or:i\d+>>          Or [<<Not1>>,<<Not2>>]
184   /// CHECK:                            Return [<<Or>>]
185 
186   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
187   /// 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 
196   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
197   /// CHECK:                            Not
198   /// CHECK-NOT:                        Not
199 
200   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
201   /// CHECK-NOT:                        Or
202 
$opt$noinline$regressInputsAway(int a, int b)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.
217   /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
218   /// CHECK:       <<P1:i\d+>>          ParameterValue
219   /// CHECK:       <<P2:i\d+>>          ParameterValue
220   /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
221   /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
222   /// CHECK:       <<Xor:i\d+>>         Xor [<<Not1>>,<<Not2>>]
223   /// CHECK:                            Return [<<Xor>>]
224 
225   /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
226   /// CHECK:       <<P1:i\d+>>          ParameterValue
227   /// CHECK:       <<P2:i\d+>>          ParameterValue
228   /// CHECK:       <<Xor:i\d+>>         Xor [<<P1>>,<<P2>>]
229   /// CHECK:                            Return [<<Xor>>]
230 
231   /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
232   /// CHECK-NOT:                        Not
233 
$opt$noinline$notXorToXor(int a, int b)234   public static int $opt$noinline$notXorToXor(int a, int b) {
235     if (doThrow) throw new Error();
236     return ~a ^ ~b;
237   }
238 
239   /**
240    * 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 
247   /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (before)
248   /// CHECK:       <<P1:z\d+>>          ParameterValue
249   /// CHECK:       <<P2:z\d+>>          ParameterValue
250   /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
251   /// CHECK:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
252   /// CHECK:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
253   /// CHECK:       <<Xor:i\d+>>         Xor [<<NotP1>>,<<NotP2>>]
254   /// CHECK:                            Return [<<Xor>>]
255 
256   /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (after)
257   /// CHECK:       <<Cond1:z\d+>>       ParameterValue
258   /// CHECK:       <<Cond2:z\d+>>       ParameterValue
259   /// CHECK:       <<Xor:i\d+>>         Xor [<<Cond1>>,<<Cond2>>]
260   /// CHECK:                            Return [<<Xor>>]
261 
262   /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
263   /// CHECK-NOT:                        BooleanNot
264 
$opt$noinline$booleanNotXorToXor(boolean a, boolean b)265   public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
266     if (doThrow) throw new Error();
267     return !a ^ !b;
268   }
269 
270   /**
271    * Check that no transformation is done when one Not has multiple uses.
272    */
273 
274   /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
275   /// CHECK:       <<P1:i\d+>>          ParameterValue
276   /// CHECK:       <<P2:i\d+>>          ParameterValue
277   /// CHECK:       <<One:i\d+>>         IntConstant 1
278   /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
279   /// CHECK:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
280   /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
281   /// CHECK:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
282   /// CHECK:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
283   /// CHECK:                            Return [<<Add>>]
284 
285   /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
286   /// 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 
296   /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
297   /// CHECK-NOT:                        Or
298 
$opt$noinline$notMultipleUses(int a, int b)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 
main(String[] args)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 }
312