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 
assertIntEquals(int expected, int result)19   public static void assertIntEquals(int expected, int result) {
20     if (expected != result) {
21       throw new Error("Expected: " + expected + ", found: " + result);
22     }
23   }
24 
assertLongEquals(long expected, long result)25   public static void assertLongEquals(long expected, long result) {
26     if (expected != result) {
27       throw new Error("Expected: " + expected + ", found: " + result);
28     }
29   }
30 
31   /**
32    * Test merging of `NOT+AND` into `BIC`.
33    */
34 
35   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (before)
36   /// CHECK:       <<Base:i\d+>>        ParameterValue
37   /// CHECK:       <<Mask:i\d+>>        ParameterValue
38   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
39   /// CHECK:       <<Op:i\d+>>          And [<<Base>>,<<Not>>]
40   /// CHECK:                            Return [<<Op>>]
41 
42   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after)
43   /// CHECK:       <<Base:i\d+>>        ParameterValue
44   /// CHECK:       <<Mask:i\d+>>        ParameterValue
45   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And
46   /// CHECK:                            Return [<<NegOp>>]
47 
48   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after)
49   /// CHECK-NOT:                        Not
50   /// CHECK-NOT:                        And
51 
52   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) disassembly (after)
53   /// CHECK:                            bic w{{\d+}}, w{{\d+}}, w{{\d+}}
54 
55 
56   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (before)
57   /// CHECK:       <<Base:i\d+>>        ParameterValue
58   /// CHECK:       <<Mask:i\d+>>        ParameterValue
59   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
60   /// CHECK:       <<Op:i\d+>>          And [<<Base>>,<<Not>>]
61   /// CHECK:                            Return [<<Op>>]
62 
63   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after)
64   /// CHECK:       <<Base:i\d+>>        ParameterValue
65   /// CHECK:       <<Mask:i\d+>>        ParameterValue
66   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And
67   /// CHECK:                            Return [<<NegOp>>]
68 
69   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after)
70   /// CHECK-NOT:                        Not
71   /// CHECK-NOT:                        And
72 
73   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) disassembly (after)
74   /// CHECK:                            bic r{{\d+}}, r{{\d+}}, r{{\d+}}
75 
$opt$noinline$notAnd(int base, int mask)76   public static int $opt$noinline$notAnd(int base, int mask) {
77     return base & ~mask;
78   }
79 
80   /**
81    * Test merging of `NOT+ORR` into `ORN`.
82    */
83 
84   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (before)
85   /// CHECK:       <<Base:j\d+>>        ParameterValue
86   /// CHECK:       <<Mask:j\d+>>        ParameterValue
87   /// CHECK:       <<Not:j\d+>>         Not [<<Mask>>]
88   /// CHECK:       <<Op:j\d+>>          Or [<<Base>>,<<Not>>]
89   /// CHECK:                            Return [<<Op>>]
90 
91   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after)
92   /// CHECK:       <<Base:j\d+>>        ParameterValue
93   /// CHECK:       <<Mask:j\d+>>        ParameterValue
94   /// CHECK:       <<NegOp:j\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or
95   /// CHECK:                            Return [<<NegOp>>]
96 
97   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after)
98   /// CHECK-NOT:                        Not
99   /// CHECK-NOT:                        Or
100 
101   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) disassembly (after)
102   /// CHECK:                            orn x{{\d+}}, x{{\d+}}, x{{\d+}}
103 
104 
105   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (before)
106   /// CHECK:       <<Base:j\d+>>        ParameterValue
107   /// CHECK:       <<Mask:j\d+>>        ParameterValue
108   /// CHECK:       <<Not:j\d+>>         Not [<<Mask>>]
109   /// CHECK:       <<Op:j\d+>>          Or [<<Base>>,<<Not>>]
110   /// CHECK:                            Return [<<Op>>]
111 
112   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after)
113   /// CHECK:       <<Base:j\d+>>        ParameterValue
114   /// CHECK:       <<Mask:j\d+>>        ParameterValue
115   /// CHECK:       <<NegOp:j\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or
116   /// CHECK:                            Return [<<NegOp>>]
117 
118   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after)
119   /// CHECK-NOT:                        Not
120   /// CHECK-NOT:                        Or
121 
122   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) disassembly (after)
123   /// CHECK:                            orn r{{\d+}}, r{{\d+}}, r{{\d+}}
124 
$opt$noinline$notOr(long base, long mask)125   public static long $opt$noinline$notOr(long base, long mask) {
126     return base | ~mask;
127   }
128 
129   /**
130    * Test merging of `NOT+EOR` into `EON`.
131    */
132 
133   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (before)
134   /// CHECK:       <<Base:i\d+>>        ParameterValue
135   /// CHECK:       <<Mask:i\d+>>        ParameterValue
136   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
137   /// CHECK:       <<Op:i\d+>>          Xor [<<Base>>,<<Not>>]
138   /// CHECK:                            Return [<<Op>>]
139 
140   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after)
141   /// CHECK:       <<Base:i\d+>>        ParameterValue
142   /// CHECK:       <<Mask:i\d+>>        ParameterValue
143   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Xor
144   /// CHECK:                            Return [<<NegOp>>]
145 
146   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after)
147   /// CHECK-NOT:                        Not
148   /// CHECK-NOT:                        Xor
149 
150   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) disassembly (after)
151   /// CHECK:                            eon w{{\d+}}, w{{\d+}}, w{{\d+}}
152 
153 
154   /// CHECK-START-ARM:   int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (before)
155   /// CHECK:       <<Base:i\d+>>        ParameterValue
156   /// CHECK:       <<Mask:i\d+>>        ParameterValue
157   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
158   /// CHECK:       <<Op:i\d+>>          Xor [<<Base>>,<<Not>>]
159   /// CHECK:                            Return [<<Op>>]
160 
161   /// CHECK-START-ARM:   int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after)
162   /// CHECK:       <<Base:i\d+>>        ParameterValue
163   /// CHECK:       <<Mask:i\d+>>        ParameterValue
164   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
165   /// CHECK:       <<Op:i\d+>>          Xor [<<Base>>,<<Not>>]
166   /// CHECK:                            Return [<<Op>>]
167 
168   /// CHECK-START-ARM:   int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after)
169   /// CHECK-NOT:                        BitwiseNegatedRight
170 
$opt$noinline$notXor(int base, int mask)171   public static int $opt$noinline$notXor(int base, int mask) {
172     return base ^ ~mask;
173   }
174 
175   /**
176    * Check that transformation is done when the argument is a constant.
177    */
178 
179   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (before)
180   /// CHECK:       <<Base:i\d+>>        ParameterValue
181   /// CHECK:       <<Constant:i\d+>>    IntConstant
182   /// CHECK:       <<Not:i\d+>>         Not [<<Base>>]
183   /// CHECK:       <<Op:i\d+>>          And [<<Not>>,<<Constant>>]
184   /// CHECK:                            Return [<<Op>>]
185 
186   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (after)
187   /// CHECK:       <<Base:i\d+>>        ParameterValue
188   /// CHECK:       <<Constant:i\d+>>    IntConstant
189   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
190   /// CHECK:                            Return [<<NegOp>>]
191 
192 
193   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (before)
194   /// CHECK:       <<Base:i\d+>>        ParameterValue
195   /// CHECK:       <<Constant:i\d+>>    IntConstant
196   /// CHECK:       <<Not:i\d+>>         Not [<<Base>>]
197   /// CHECK:       <<Op:i\d+>>          And [<<Not>>,<<Constant>>]
198   /// CHECK:                            Return [<<Op>>]
199 
200   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (after)
201   /// CHECK:       <<Base:i\d+>>        ParameterValue
202   /// CHECK:       <<Constant:i\d+>>    IntConstant
203   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
204   /// CHECK:                            Return [<<NegOp>>]
205 
$opt$noinline$notAndConstant(int mask)206   public static int $opt$noinline$notAndConstant(int mask) {
207     return 0xf & ~mask;
208   }
209 
210   /**
211    * Check that no transformation is done when Not has multiple uses.
212    */
213 
214   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (before)
215   /// CHECK:       <<Base:i\d+>>        ParameterValue
216   /// CHECK:       <<Mask:i\d+>>        ParameterValue
217   /// CHECK:       <<One:i\d+>>         IntConstant
218   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
219   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
220   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
221   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
222   /// CHECK:                            Return [<<Add>>]
223 
224   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after)
225   /// CHECK:       <<Base:i\d+>>        ParameterValue
226   /// CHECK:       <<Mask:i\d+>>        ParameterValue
227   /// CHECK:       <<One:i\d+>>         IntConstant
228   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
229   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
230   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
231   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
232   /// CHECK:                            Return [<<Add>>]
233 
234   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after)
235   /// CHECK-NOT:                        BitwiseNegatedRight
236 
237 
238   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (before)
239   /// CHECK:       <<Base:i\d+>>        ParameterValue
240   /// CHECK:       <<Mask:i\d+>>        ParameterValue
241   /// CHECK:       <<One:i\d+>>         IntConstant
242   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
243   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
244   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
245   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
246   /// CHECK:                            Return [<<Add>>]
247 
248   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after)
249   /// CHECK:       <<Base:i\d+>>        ParameterValue
250   /// CHECK:       <<Mask:i\d+>>        ParameterValue
251   /// CHECK:       <<One:i\d+>>         IntConstant
252   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
253   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
254   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
255   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
256   /// CHECK:                            Return [<<Add>>]
257 
258   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after)
259   /// CHECK-NOT:                        BitwiseNegatedRight
260 
$opt$noinline$notAndMultipleUses(int base, int mask)261   public static int $opt$noinline$notAndMultipleUses(int base, int mask) {
262     int tmp = ~mask;
263     return (tmp & 0x1) + (base & tmp);
264   }
265 
266   /**
267    * Check that no transformation is done when both inputs are Not's.
268    */
269 
270   // We don't check the instructions before the pass, since if De Morgan's laws
271   // have been applied then Not/Not/Or is replaced by And/Not.
272 
273   /// CHECK-START-ARM64: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm64 (after)
274   /// CHECK-NOT:                        BitwiseNegatedRight
275 
276   /// CHECK-START-ARM:   int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm (after)
277   /// CHECK-NOT:                        BitwiseNegatedRight
278 
$opt$noinline$deMorganOr(int a, int b)279   public static int $opt$noinline$deMorganOr(int a, int b) {
280     return ~a | ~b;
281   }
282 
main(String[] args)283   public static void main(String[] args) {
284     assertIntEquals(0xe,   $opt$noinline$notAnd(0xf, 0x1));
285     assertLongEquals(~0x0, $opt$noinline$notOr(0xf, 0x1));
286     assertIntEquals(~0xe,  $opt$noinline$notXor(0xf, 0x1));
287     assertIntEquals(0xe,  $opt$noinline$notAndConstant(0x1));
288     assertIntEquals(0xe,   $opt$noinline$notAndMultipleUses(0xf, 0x1));
289     assertIntEquals(~0x1,  $opt$noinline$deMorganOr(0x3, 0x1));
290   }
291 }
292