blob: ccb8ff4fdff2db272e229368fb912838427cbbac [file] [log] [blame]
Kevin Brodsky9ff0d202016-01-11 13:43:31 +00001/*
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 merging of `NOT+AND` into `BIC`.
36 */
37
38 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (before)
39 /// CHECK: <<Base:i\d+>> ParameterValue
40 /// CHECK: <<Mask:i\d+>> ParameterValue
41 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
42 /// CHECK: <<Op:i\d+>> And [<<Base>>,<<Not>>]
43 /// CHECK: Return [<<Op>>]
44
45 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after)
46 /// CHECK: <<Base:i\d+>> ParameterValue
47 /// CHECK: <<Mask:i\d+>> ParameterValue
Artem Serov7fc63502016-02-09 17:15:29 +000048 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And
Kevin Brodsky9ff0d202016-01-11 13:43:31 +000049 /// CHECK: Return [<<NegOp>>]
50
51 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after)
52 /// CHECK-NOT: Not
53 /// CHECK-NOT: And
54
55 /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) disassembly (after)
56 /// CHECK: bic w{{\d+}}, w{{\d+}}, w{{\d+}}
57
Artem Serov7fc63502016-02-09 17:15:29 +000058
59 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (before)
60 /// CHECK: <<Base:i\d+>> ParameterValue
61 /// CHECK: <<Mask:i\d+>> ParameterValue
62 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
63 /// CHECK: <<Op:i\d+>> And [<<Base>>,<<Not>>]
64 /// CHECK: Return [<<Op>>]
65
66 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after)
67 /// CHECK: <<Base:i\d+>> ParameterValue
68 /// CHECK: <<Mask:i\d+>> ParameterValue
69 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And
70 /// CHECK: Return [<<NegOp>>]
71
72 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after)
73 /// CHECK-NOT: Not
74 /// CHECK-NOT: And
75
76 /// CHECK-START-ARM: int Main.$opt$noinline$notAnd(int, int) disassembly (after)
77 /// CHECK: bic.w r{{\d+}}, r{{\d+}}, r{{\d+}}
78
Kevin Brodsky9ff0d202016-01-11 13:43:31 +000079 public static int $opt$noinline$notAnd(int base, int mask) {
80 if (doThrow) throw new Error();
81 return base & ~mask;
82 }
83
84 /**
85 * Test merging of `NOT+ORR` into `ORN`.
86 */
87
88 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (before)
89 /// CHECK: <<Base:j\d+>> ParameterValue
90 /// CHECK: <<Mask:j\d+>> ParameterValue
91 /// CHECK: <<Not:j\d+>> Not [<<Mask>>]
92 /// CHECK: <<Op:j\d+>> Or [<<Base>>,<<Not>>]
93 /// CHECK: Return [<<Op>>]
94
95 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after)
96 /// CHECK: <<Base:j\d+>> ParameterValue
97 /// CHECK: <<Mask:j\d+>> ParameterValue
Artem Serov7fc63502016-02-09 17:15:29 +000098 /// CHECK: <<NegOp:j\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or
Kevin Brodsky9ff0d202016-01-11 13:43:31 +000099 /// CHECK: Return [<<NegOp>>]
100
101 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after)
102 /// CHECK-NOT: Not
103 /// CHECK-NOT: Or
104
105 /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) disassembly (after)
106 /// CHECK: orn x{{\d+}}, x{{\d+}}, x{{\d+}}
107
Artem Serov7fc63502016-02-09 17:15:29 +0000108
109 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (before)
110 /// CHECK: <<Base:j\d+>> ParameterValue
111 /// CHECK: <<Mask:j\d+>> ParameterValue
112 /// CHECK: <<Not:j\d+>> Not [<<Mask>>]
113 /// CHECK: <<Op:j\d+>> Or [<<Base>>,<<Not>>]
114 /// CHECK: Return [<<Op>>]
115
116 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after)
117 /// CHECK: <<Base:j\d+>> ParameterValue
118 /// CHECK: <<Mask:j\d+>> ParameterValue
119 /// CHECK: <<NegOp:j\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or
120 /// CHECK: Return [<<NegOp>>]
121
122 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after)
123 /// CHECK-NOT: Not
124 /// CHECK-NOT: Or
125
126 /// CHECK-START-ARM: long Main.$opt$noinline$notOr(long, long) disassembly (after)
127 /// CHECK: orn.w r{{\d+}}, r{{\d+}}, r{{\d+}}
128
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000129 public static long $opt$noinline$notOr(long base, long mask) {
130 if (doThrow) throw new Error();
131 return base | ~mask;
132 }
133
134 /**
135 * Test merging of `NOT+EOR` into `EON`.
136 */
137
138 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (before)
139 /// CHECK: <<Base:i\d+>> ParameterValue
140 /// CHECK: <<Mask:i\d+>> ParameterValue
141 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
142 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>]
143 /// CHECK: Return [<<Op>>]
144
145 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after)
146 /// CHECK: <<Base:i\d+>> ParameterValue
147 /// CHECK: <<Mask:i\d+>> ParameterValue
Artem Serov7fc63502016-02-09 17:15:29 +0000148 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Xor
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000149 /// CHECK: Return [<<NegOp>>]
150
151 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after)
152 /// CHECK-NOT: Not
153 /// CHECK-NOT: Xor
154
155 /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) disassembly (after)
156 /// CHECK: eon w{{\d+}}, w{{\d+}}, w{{\d+}}
157
Artem Serov7fc63502016-02-09 17:15:29 +0000158
159 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (before)
160 /// CHECK: <<Base:i\d+>> ParameterValue
161 /// CHECK: <<Mask:i\d+>> ParameterValue
162 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
163 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>]
164 /// CHECK: Return [<<Op>>]
165
166 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after)
167 /// CHECK: <<Base:i\d+>> ParameterValue
168 /// CHECK: <<Mask:i\d+>> ParameterValue
169 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
170 /// CHECK: <<Op:i\d+>> Xor [<<Base>>,<<Not>>]
171 /// CHECK: Return [<<Op>>]
172
173 /// CHECK-START-ARM: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after)
174 /// CHECK-NOT: BitwiseNegatedRight
175
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000176 public static int $opt$noinline$notXor(int base, int mask) {
177 if (doThrow) throw new Error();
178 return base ^ ~mask;
179 }
180
181 /**
Artem Serov7fc63502016-02-09 17:15:29 +0000182 * Check that transformation is done when the argument is a constant.
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000183 */
184
Artem Serov7fc63502016-02-09 17:15:29 +0000185 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (before)
186 /// CHECK: <<Base:i\d+>> ParameterValue
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000187 /// CHECK: <<Constant:i\d+>> IntConstant
Artem Serov7fc63502016-02-09 17:15:29 +0000188 /// CHECK: <<Not:i\d+>> Not [<<Base>>]
189 /// CHECK: <<Op:i\d+>> And [<<Not>>,<<Constant>>]
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000190 /// CHECK: Return [<<Op>>]
191
Artem Serov7fc63502016-02-09 17:15:29 +0000192 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (after)
193 /// CHECK: <<Base:i\d+>> ParameterValue
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000194 /// CHECK: <<Constant:i\d+>> IntConstant
Artem Serov7fc63502016-02-09 17:15:29 +0000195 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000196 /// CHECK: Return [<<NegOp>>]
197
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000198
Artem Serov7fc63502016-02-09 17:15:29 +0000199 /// CHECK-START-ARM: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (before)
200 /// CHECK: <<Base:i\d+>> ParameterValue
201 /// CHECK: <<Constant:i\d+>> IntConstant
202 /// CHECK: <<Not:i\d+>> Not [<<Base>>]
203 /// CHECK: <<Op:i\d+>> And [<<Not>>,<<Constant>>]
204 /// CHECK: Return [<<Op>>]
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000205
Artem Serov7fc63502016-02-09 17:15:29 +0000206 /// CHECK-START-ARM: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (after)
207 /// CHECK: <<Base:i\d+>> ParameterValue
208 /// CHECK: <<Constant:i\d+>> IntConstant
209 /// CHECK: <<NegOp:i\d+>> BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
210 /// CHECK: Return [<<NegOp>>]
211
212 public static int $opt$noinline$notAndConstant(int mask) {
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000213 if (doThrow) throw new Error();
Artem Serov7fc63502016-02-09 17:15:29 +0000214 return 0xf & ~mask;
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000215 }
216
217 /**
218 * Check that no transformation is done when Not has multiple uses.
219 */
220
221 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (before)
222 /// CHECK: <<Base:i\d+>> ParameterValue
223 /// CHECK: <<Mask:i\d+>> ParameterValue
224 /// CHECK: <<One:i\d+>> IntConstant
225 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
226 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>]
227 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>]
228 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>]
229 /// CHECK: Return [<<Add>>]
230
231 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after)
232 /// CHECK: <<Base:i\d+>> ParameterValue
233 /// CHECK: <<Mask:i\d+>> ParameterValue
234 /// CHECK: <<One:i\d+>> IntConstant
235 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
236 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>]
237 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>]
238 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>]
239 /// CHECK: Return [<<Add>>]
240
241 /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after)
Artem Serov7fc63502016-02-09 17:15:29 +0000242 /// CHECK-NOT: BitwiseNegatedRight
243
244
245 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (before)
246 /// CHECK: <<Base:i\d+>> ParameterValue
247 /// CHECK: <<Mask:i\d+>> ParameterValue
248 /// CHECK: <<One:i\d+>> IntConstant
249 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
250 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>]
251 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>]
252 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>]
253 /// CHECK: Return [<<Add>>]
254
255 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after)
256 /// CHECK: <<Base:i\d+>> ParameterValue
257 /// CHECK: <<Mask:i\d+>> ParameterValue
258 /// CHECK: <<One:i\d+>> IntConstant
259 /// CHECK: <<Not:i\d+>> Not [<<Mask>>]
260 /// CHECK: <<Op1:i\d+>> And [<<Not>>,<<One>>]
261 /// CHECK: <<Op2:i\d+>> And [<<Base>>,<<Not>>]
262 /// CHECK: <<Add:i\d+>> Add [<<Op1>>,<<Op2>>]
263 /// CHECK: Return [<<Add>>]
264
265 /// CHECK-START-ARM: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after)
266 /// CHECK-NOT: BitwiseNegatedRight
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000267
268 public static int $opt$noinline$notAndMultipleUses(int base, int mask) {
269 if (doThrow) throw new Error();
270 int tmp = ~mask;
271 return (tmp & 0x1) + (base & tmp);
272 }
273
274 /**
275 * Check that no transformation is done when both inputs are Not's.
276 */
277
278 // We don't check the instructions before the pass, since if De Morgan's laws
279 // have been applied then Not/Not/Or is replaced by And/Not.
280
281 /// CHECK-START-ARM64: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm64 (after)
Artem Serov7fc63502016-02-09 17:15:29 +0000282 /// CHECK-NOT: BitwiseNegatedRight
283
284 /// CHECK-START-ARM: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm (after)
285 /// CHECK-NOT: BitwiseNegatedRight
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000286
287 public static int $opt$noinline$deMorganOr(int a, int b) {
288 if (doThrow) throw new Error();
289 return ~a | ~b;
290 }
291
292 public static void main(String[] args) {
293 assertIntEquals(0xe, $opt$noinline$notAnd(0xf, 0x1));
294 assertLongEquals(~0x0, $opt$noinline$notOr(0xf, 0x1));
295 assertIntEquals(~0xe, $opt$noinline$notXor(0xf, 0x1));
Artem Serov7fc63502016-02-09 17:15:29 +0000296 assertIntEquals(0xe, $opt$noinline$notAndConstant(0x1));
Kevin Brodsky9ff0d202016-01-11 13:43:31 +0000297 assertIntEquals(0xe, $opt$noinline$notAndMultipleUses(0xf, 0x1));
298 assertIntEquals(~0x1, $opt$noinline$deMorganOr(0x3, 0x1));
299 }
300}