1# Copyright (C) 2017 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#      http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15.class public LSmaliTests;
16.super Ljava/lang/Object;
17
18#
19# Test transformation of Not/Not/And into Or/Not.
20#
21
22## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
23## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
24## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
25## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
26## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
27## CHECK-DAG:       <<And:i\d+>>         And [<<Not1>>,<<Not2>>]
28## CHECK-DAG:                            Return [<<And>>]
29
30## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
31## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
32## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
33## CHECK-DAG:       <<Or:i\d+>>          Or [<<P1>>,<<P2>>]
34## CHECK-DAG:       <<Not:i\d+>>         Not [<<Or>>]
35## CHECK-DAG:                            Return [<<Not>>]
36
37## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
38## CHECK-DAG:                            Not
39## CHECK-NOT:                            Not
40
41## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
42## CHECK-NOT:                            And
43.method public static $opt$noinline$andToOr(II)I
44    .registers 4
45    .param p0, "a"    # I
46    .param p1, "b"    # I
47
48    .prologue
49    # return ~a & ~b;
50    not-int v0, p0
51    not-int v1, p1
52    and-int/2addr v0, v1
53
54    return v0
55.end method
56
57# Test transformation of Not/Not/And into Or/Not for boolean negations.
58# Note that the graph before this instruction simplification pass does not
59# contain `HBooleanNot` instructions. This is because this transformation
60# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
61# same pass.
62
63## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (before)
64## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
65## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
66## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
67## CHECK-DAG:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
68## CHECK-DAG:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
69## CHECK-DAG:       <<And:i\d+>>         And [<<NotP1>>,<<NotP2>>]
70## CHECK-DAG:                            Return [<<And>>]
71
72## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (after)
73## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
74## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
75## CHECK-DAG:       <<Or:i\d+>>          Or [<<Cond1>>,<<Cond2>>]
76## CHECK-DAG:       <<BooleanNot:z\d+>>  BooleanNot [<<Or>>]
77## CHECK-DAG:                            Return [<<BooleanNot>>]
78
79## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
80## CHECK-DAG:                            BooleanNot
81## CHECK-NOT:                            BooleanNot
82
83## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
84## CHECK-NOT:                            And
85.method public static $opt$noinline$booleanAndToOr(ZZ)Z
86    .registers 4
87    .param p0, "a"    # Z
88    .param p1, "b"    # Z
89
90    .prologue
91    # return !a & !b;
92    xor-int/lit8 v0, p0, 0x1
93    xor-int/lit8 v1, p1, 0x1
94    and-int/2addr v0, v1
95    return v0
96.end method
97
98# Test transformation of Not/Not/Or into And/Not.
99
100## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
101## CHECK-DAG:       <<P1:j\d+>>          ParameterValue
102## CHECK-DAG:       <<P2:j\d+>>          ParameterValue
103## CHECK-DAG:       <<Not1:j\d+>>        Not [<<P1>>]
104## CHECK-DAG:       <<Not2:j\d+>>        Not [<<P2>>]
105## CHECK-DAG:       <<Or:j\d+>>          Or [<<Not1>>,<<Not2>>]
106## CHECK-DAG:                            Return [<<Or>>]
107
108## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
109## CHECK-DAG:       <<P1:j\d+>>          ParameterValue
110## CHECK-DAG:       <<P2:j\d+>>          ParameterValue
111## CHECK-DAG:       <<And:j\d+>>         And [<<P1>>,<<P2>>]
112## CHECK-DAG:       <<Not:j\d+>>         Not [<<And>>]
113## CHECK-DAG:                            Return [<<Not>>]
114
115## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
116## CHECK-DAG:                            Not
117## CHECK-NOT:                            Not
118
119## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
120## CHECK-NOT:                            Or
121.method public static $opt$noinline$orToAnd(JJ)J
122    .registers 8
123    .param p0, "a"    # J
124    .param p2, "b"    # J
125
126    .prologue
127    # return ~a | ~b;
128    not-long v0, p0
129    not-long v2, p2
130    or-long/2addr v0, v2
131    return-wide v0
132.end method
133
134# 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## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (before)
141## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
142## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
143## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
144## CHECK-DAG:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
145## CHECK-DAG:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
146## CHECK-DAG:       <<Or:i\d+>>          Or [<<NotP1>>,<<NotP2>>]
147## CHECK-DAG:                            Return [<<Or>>]
148
149## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (after)
150## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
151## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
152## CHECK-DAG:       <<And:i\d+>>         And [<<Cond1>>,<<Cond2>>]
153## CHECK-DAG:       <<BooleanNot:z\d+>>  BooleanNot [<<And>>]
154## CHECK-DAG:                            Return [<<BooleanNot>>]
155
156## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
157## CHECK-DAG:                            BooleanNot
158## CHECK-NOT:                            BooleanNot
159
160## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
161## CHECK-NOT:                            Or
162.method public static $opt$noinline$booleanOrToAnd(ZZ)Z
163    .registers 4
164    .param p0, "a"    # Z
165    .param p1, "b"    # Z
166
167    .prologue
168    # return !a | !b;
169    xor-int/lit8 v0, p0, 0x1
170    xor-int/lit8 v1, p1, 0x1
171    or-int/2addr v0, v1
172    return v0
173.end method
174
175# Test that the transformation copes with inputs being separated from the
176# bitwise operations.
177# This is a regression test. The initial logic was inserting the new bitwise
178# operation incorrectly.
179
180## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
181## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
182## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
183## CHECK-DAG:       <<Cst1:i\d+>>        IntConstant 1
184## CHECK-DAG:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
185## CHECK-DAG:       <<Not1:i\d+>>        Not [<<AddP1>>]
186## CHECK-DAG:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
187## CHECK-DAG:       <<Not2:i\d+>>        Not [<<AddP2>>]
188## CHECK-DAG:       <<Or:i\d+>>          Or [<<Not1>>,<<Not2>>]
189## CHECK-DAG:                            Return [<<Or>>]
190
191## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
192## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
193## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
194## CHECK-DAG:       <<Cst1:i\d+>>        IntConstant 1
195## CHECK-DAG:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
196## CHECK-DAG:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
197## CHECK-DAG:       <<And:i\d+>>         And [<<AddP1>>,<<AddP2>>]
198## CHECK-DAG:       <<Not:i\d+>>         Not [<<And>>]
199## CHECK-DAG:                            Return [<<Not>>]
200
201## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
202## CHECK-DAG:                            Not
203## CHECK-NOT:                            Not
204
205## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
206## CHECK-NOT:                            Or
207.method public static $opt$noinline$regressInputsAway(II)I
208    .registers 7
209    .param p0, "a"    # I
210    .param p1, "b"    # I
211
212    .prologue
213    # int a1 = a + 1;
214    add-int/lit8 v0, p0, 0x1
215    # int not_a1 = ~a1;
216    not-int v2, v0
217    # int b1 = b + 1;
218    add-int/lit8 v1, p1, 0x1
219    # int not_b1 = ~b1;
220    not-int v3, v1
221
222    # return not_a1 | not_b1
223    or-int v4, v2, v3
224    return v4
225.end method
226
227# Test transformation of Not/Not/Xor into Xor.
228
229# See first note above.
230## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
231## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
232## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
233## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
234## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
235## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<Not1>>,<<Not2>>]
236## CHECK-DAG:                            Return [<<Xor>>]
237
238## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
239## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
240## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
241## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<P1>>,<<P2>>]
242## CHECK-DAG:                            Return [<<Xor>>]
243
244## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
245## CHECK-NOT:                            Not
246.method public static $opt$noinline$notXorToXor(II)I
247    .registers 4
248    .param p0, "a"    # I
249    .param p1, "b"    # I
250
251    .prologue
252    # return ~a ^ ~b;
253    not-int v0, p0
254    not-int v1, p1
255    xor-int/2addr v0, v1
256    return v0
257.end method
258
259# Test transformation of Not/Not/Xor into Xor for boolean negations.
260# Note that the graph before this instruction simplification pass does not
261# contain `HBooleanNot` instructions. This is because this transformation
262# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
263# same pass.
264
265## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (before)
266## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
267## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
268## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
269## CHECK-DAG:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
270## CHECK-DAG:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
271## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<NotP1>>,<<NotP2>>]
272## CHECK-DAG:                            Return [<<Xor>>]
273
274## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (after)
275## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
276## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
277## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<Cond1>>,<<Cond2>>]
278## CHECK-DAG:                            Return [<<Xor>>]
279
280## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
281## CHECK-NOT:                            BooleanNot
282.method public static $opt$noinline$booleanNotXorToXor(ZZ)Z
283    .registers 4
284    .param p0, "a"    # Z
285    .param p1, "b"    # Z
286
287    .prologue
288    # return !a ^ !b;
289    xor-int/lit8 v0, p0, 0x1
290    xor-int/lit8 v1, p1, 0x1
291    xor-int/2addr v0, v1
292    return v0
293.end method
294
295# Check that no transformation is done when one Not has multiple uses.
296
297## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
298## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
299## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
300## CHECK-DAG:       <<One:i\d+>>         IntConstant 1
301## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
302## CHECK-DAG:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
303## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
304## CHECK-DAG:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
305## CHECK-DAG:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
306## CHECK-DAG:                            Return [<<Add>>]
307
308## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
309## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
310## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
311## CHECK-DAG:       <<One:i\d+>>         IntConstant 1
312## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
313## CHECK-DAG:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
314## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
315## CHECK-DAG:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
316## CHECK-DAG:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
317## CHECK-DAG:                            Return [<<Add>>]
318
319## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
320## CHECK-NOT:                            Or
321.method public static $opt$noinline$notMultipleUses(II)I
322    .registers 5
323    .param p0, "a"    # I
324    .param p1, "b"    # I
325
326    .prologue
327    # int tmp = ~b;
328    not-int v0, p1
329    # return (tmp & 0x1) + (~a & tmp);
330    and-int/lit8 v1, v0, 0x1
331    not-int v2, p0
332    and-int/2addr v2, v0
333    add-int/2addr v1, v2
334    return v1
335.end method
336
337
338# Test transformation of Not/Not/And into Or/Not.
339
340# Note: before the instruction_simplifier pass, Xor's are used instead of
341# Not's (the simplification happens during the same pass).
342## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (before)
343## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
344## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
345## CHECK-DAG:       <<CstM1:i\d+>>       IntConstant -1
346## CHECK-DAG:       <<Not1:i\d+>>        Xor [<<P1>>,<<CstM1>>]
347## CHECK-DAG:       <<Not2:i\d+>>        Xor [<<P2>>,<<CstM1>>]
348## CHECK-DAG:       <<And:i\d+>>         And [<<Not1>>,<<Not2>>]
349## CHECK-DAG:                            Return [<<And>>]
350
351## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after)
352## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
353## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
354## CHECK-DAG:       <<Or:i\d+>>          Or [<<P1>>,<<P2>>]
355## CHECK-DAG:       <<Not:i\d+>>         Not [<<Or>>]
356## CHECK-DAG:                            Return [<<Not>>]
357
358## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after)
359## CHECK-DAG:                            Not
360## CHECK-NOT:                            Not
361
362## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after)
363## CHECK-NOT:                            And
364
365# Original java source:
366#
367#     public static int $opt$noinline$andToOr(int a, int b) {
368#       return ~a & ~b;
369#     }
370
371.method public static $opt$noinline$andToOrV2(II)I
372    .registers 4
373    .param p0, "a"    # I
374    .param p1, "b"    # I
375
376    .prologue
377    .line 85
378    xor-int/lit8 v0, p0, -0x1
379
380    xor-int/lit8 v1, p1, -0x1
381
382    and-int/2addr v0, v1
383
384    return v0
385.end method
386
387
388# Test transformation of Not/Not/And into Or/Not for boolean negations.
389# Note that the graph before this instruction simplification pass does not
390# contain `HBooleanNot` instructions. This is because this transformation
391# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
392# same pass.
393
394## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (before)
395## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
396## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
397## CHECK-DAG:       <<Const0:i\d+>>      IntConstant 0
398## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
399## CHECK-DAG:       <<Select1:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P1>>]
400## CHECK-DAG:       <<Select2:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P2>>]
401## CHECK-DAG:       <<And:i\d+>>         And [<<Select1>>,<<Select2>>]
402## CHECK-DAG:                            Return [<<And>>]
403
404## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (after)
405## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
406## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
407## CHECK-DAG:       <<Or:i\d+>>          Or [<<Cond1>>,<<Cond2>>]
408## CHECK-DAG:       <<BooleanNot:z\d+>>  BooleanNot [<<Or>>]
409## CHECK-DAG:                            Return [<<BooleanNot>>]
410
411## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after)
412## CHECK-DAG:                            BooleanNot
413## CHECK-NOT:                            BooleanNot
414
415## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after)
416## CHECK-NOT:                            And
417
418# Original java source:
419#
420#     public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
421#       return !a & !b;
422#     }
423
424.method public static $opt$noinline$booleanAndToOrV2(ZZ)Z
425    .registers 5
426    .param p0, "a"    # Z
427    .param p1, "b"    # Z
428
429    .prologue
430    const/4 v0, 0x1
431
432    const/4 v1, 0x0
433
434    .line 122
435    if-nez p0, :cond_13
436
437    move v2, v0
438
439    :goto_f
440    if-nez p1, :cond_15
441
442    :goto_11
443    and-int/2addr v0, v2
444
445    return v0
446
447    :cond_13
448    move v2, v1
449
450    goto :goto_f
451
452    :cond_15
453    move v0, v1
454
455    goto :goto_11
456.end method
457
458
459# Test transformation of Not/Not/Or into And/Not.
460
461# See note above.
462# The second Xor has its arguments reversed for no obvious reason.
463## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (before)
464## CHECK-DAG:       <<P1:j\d+>>          ParameterValue
465## CHECK-DAG:       <<P2:j\d+>>          ParameterValue
466## CHECK-DAG:       <<CstM1:j\d+>>       LongConstant -1
467## CHECK-DAG:       <<Not1:j\d+>>        Xor [<<P1>>,<<CstM1>>]
468## CHECK-DAG:       <<Not2:j\d+>>        Xor [<<CstM1>>,<<P2>>]
469## CHECK-DAG:       <<Or:j\d+>>          Or [<<Not1>>,<<Not2>>]
470## CHECK-DAG:                            Return [<<Or>>]
471
472## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after)
473## CHECK-DAG:       <<P1:j\d+>>          ParameterValue
474## CHECK-DAG:       <<P2:j\d+>>          ParameterValue
475## CHECK-DAG:       <<And:j\d+>>         And [<<P1>>,<<P2>>]
476## CHECK-DAG:       <<Not:j\d+>>         Not [<<And>>]
477## CHECK-DAG:                            Return [<<Not>>]
478
479## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after)
480## CHECK-DAG:                            Not
481## CHECK-NOT:                            Not
482
483## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after)
484## CHECK-NOT:                            Or
485
486# Original java source:
487#
488#     public static long $opt$noinline$orToAnd(long a, long b) {
489#       return ~a | ~b;
490#     }
491
492.method public static $opt$noinline$orToAndV2(JJ)J
493    .registers 8
494    .param p0, "a"    # J
495    .param p2, "b"    # J
496
497    .prologue
498    const-wide/16 v2, -0x1
499
500    .line 156
501    xor-long v0, p0, v2
502
503    xor-long/2addr v2, p2
504
505    or-long/2addr v0, v2
506
507    return-wide v0
508.end method
509
510# Test transformation of Not/Not/Or into Or/And for boolean negations.
511# Note that the graph before this instruction simplification pass does not
512# contain `HBooleanNot` instructions. This is because this transformation
513# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
514# same pass.
515
516## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (before)
517## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
518## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
519## CHECK-DAG:       <<Const0:i\d+>>      IntConstant 0
520## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
521## CHECK-DAG:       <<Select1:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P1>>]
522## CHECK-DAG:       <<Select2:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P2>>]
523## CHECK-DAG:       <<Or:i\d+>>          Or [<<Select1>>,<<Select2>>]
524## CHECK-DAG:                            Return [<<Or>>]
525
526## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (after)
527## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
528## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
529## CHECK-DAG:       <<And:i\d+>>         And [<<Cond1>>,<<Cond2>>]
530## CHECK-DAG:       <<BooleanNot:z\d+>>  BooleanNot [<<And>>]
531## CHECK-DAG:                            Return [<<BooleanNot>>]
532
533## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after)
534## CHECK-DAG:                            BooleanNot
535## CHECK-NOT:                            BooleanNot
536
537## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after)
538## CHECK-NOT:                            Or
539
540# Original java source:
541#
542#     public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
543#       return !a | !b;
544#     }
545
546.method public static $opt$noinline$booleanOrToAndV2(ZZ)Z
547    .registers 5
548    .param p0, "a"    # Z
549    .param p1, "b"    # Z
550
551    .prologue
552    const/4 v0, 0x1
553
554    const/4 v1, 0x0
555
556    .line 193
557    if-nez p0, :cond_13
558
559    move v2, v0
560
561    :goto_f
562    if-nez p1, :cond_15
563
564    :goto_11
565    or-int/2addr v0, v2
566
567    return v0
568
569    :cond_13
570    move v2, v1
571
572    goto :goto_f
573
574    :cond_15
575    move v0, v1
576
577    goto :goto_11
578.end method
579
580
581# Test that the transformation copes with inputs being separated from the
582# bitwise operations.
583# This is a regression test. The initial logic was inserting the new bitwise
584# operation incorrectly.
585
586## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (before)
587## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
588## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
589## CHECK-DAG:       <<Cst1:i\d+>>        IntConstant 1
590## CHECK-DAG:       <<CstM1:i\d+>>       IntConstant -1
591## CHECK-DAG:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
592## CHECK-DAG:       <<Not1:i\d+>>        Xor [<<AddP1>>,<<CstM1>>]
593## CHECK-DAG:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
594## CHECK-DAG:       <<Not2:i\d+>>        Xor [<<AddP2>>,<<CstM1>>]
595## CHECK-DAG:       <<Or:i\d+>>          Or [<<Not1>>,<<Not2>>]
596## CHECK-DAG:                            Return [<<Or>>]
597
598## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after)
599## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
600## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
601## CHECK-DAG:       <<Cst1:i\d+>>        IntConstant 1
602## CHECK-DAG:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
603## CHECK-DAG:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
604## CHECK-DAG:       <<And:i\d+>>         And [<<AddP1>>,<<AddP2>>]
605## CHECK-DAG:       <<Not:i\d+>>         Not [<<And>>]
606## CHECK-DAG:                            Return [<<Not>>]
607
608## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after)
609## CHECK-DAG:                            Not
610## CHECK-NOT:                            Not
611
612## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after)
613## CHECK-NOT:                            Or
614
615# Original java source:
616#
617#     public static int $opt$noinline$regressInputsAway(int a, int b) {
618#       int a1 = a + 1;
619#       int not_a1 = ~a1;
620#       int b1 = b + 1;
621#       int not_b1 = ~b1;
622#       return not_a1 | not_b1;
623#     }
624
625.method public static $opt$noinline$regressInputsAwayV2(II)I
626    .registers 7
627    .param p0, "a"    # I
628    .param p1, "b"    # I
629
630    .prologue
631    .line 234
632    add-int/lit8 v0, p0, 0x1
633
634    .line 236
635    .local v0, "a1":I
636    xor-int/lit8 v2, v0, -0x1
637
638    .line 237
639    .local v2, "not_a1":I
640    add-int/lit8 v1, p1, 0x1
641
642    .line 238
643    .local v1, "b1":I
644    xor-int/lit8 v3, v1, -0x1
645
646    .line 239
647    .local v3, "not_b1":I
648    or-int v4, v2, v3
649
650    return v4
651.end method
652
653
654# Test transformation of Not/Not/Xor into Xor.
655
656# See first note above.
657## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (before)
658## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
659## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
660## CHECK-DAG:       <<CstM1:i\d+>>       IntConstant -1
661## CHECK-DAG:       <<Not1:i\d+>>        Xor [<<P1>>,<<CstM1>>]
662## CHECK-DAG:       <<Not2:i\d+>>        Xor [<<P2>>,<<CstM1>>]
663## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<Not1>>,<<Not2>>]
664## CHECK-DAG:                            Return [<<Xor>>]
665
666## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after)
667## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
668## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
669## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<P1>>,<<P2>>]
670## CHECK-DAG:                            Return [<<Xor>>]
671
672## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after)
673## CHECK-NOT:                            Not
674
675# Original java source:
676#
677#     public static int $opt$noinline$notXorToXor(int a, int b) {
678#       return ~a ^ ~b;
679#     }
680
681.method public static $opt$noinline$notXorToXorV2(II)I
682    .registers 4
683    .param p0, "a"    # I
684    .param p1, "b"    # I
685
686    .prologue
687    .line 266
688    xor-int/lit8 v0, p0, -0x1
689
690    xor-int/lit8 v1, p1, -0x1
691
692    xor-int/2addr v0, v1
693
694    return v0
695.end method
696
697
698# Test transformation of Not/Not/Xor into Xor for boolean negations.
699# Note that the graph before this instruction simplification pass does not
700# contain `HBooleanNot` instructions. This is because this transformation
701# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
702# same pass.
703
704## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (before)
705## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
706## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
707## CHECK-DAG:       <<Const0:i\d+>>      IntConstant 0
708## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
709## CHECK-DAG:       <<Select1:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P1>>]
710## CHECK-DAG:       <<Select2:i\d+>>     Select [<<Const1>>,<<Const0>>,<<P2>>]
711## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<Select1>>,<<Select2>>]
712## CHECK-DAG:                            Return [<<Xor>>]
713
714## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (after)
715## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
716## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
717## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<Cond1>>,<<Cond2>>]
718## CHECK-DAG:                            Return [<<Xor>>]
719
720## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_bce (after)
721## CHECK-NOT:                            BooleanNot
722
723# Original java source:
724#
725#     public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
726#       return !a ^ !b;
727#     }
728
729.method public static $opt$noinline$booleanNotXorToXorV2(ZZ)Z
730    .registers 5
731    .param p0, "a"    # Z
732    .param p1, "b"    # Z
733
734    .prologue
735    const/4 v0, 0x1
736
737    const/4 v1, 0x0
738
739    .line 298
740    if-nez p0, :cond_13
741
742    move v2, v0
743
744    :goto_f
745    if-nez p1, :cond_15
746
747    :goto_11
748    xor-int/2addr v0, v2
749
750    return v0
751
752    :cond_13
753    move v2, v1
754
755    goto :goto_f
756
757    :cond_15
758    move v0, v1
759
760    goto :goto_11
761.end method
762
763
764# Check that no transformation is done when one Not has multiple uses.
765
766## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (before)
767## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
768## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
769## CHECK-DAG:       <<CstM1:i\d+>>       IntConstant -1
770## CHECK-DAG:       <<One:i\d+>>         IntConstant 1
771## CHECK-DAG:       <<Not2:i\d+>>        Xor [<<P2>>,<<CstM1>>]
772## CHECK-DAG:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
773## CHECK-DAG:       <<Not1:i\d+>>        Xor [<<P1>>,<<CstM1>>]
774## CHECK-DAG:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
775## CHECK-DAG:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
776## CHECK-DAG:                            Return [<<Add>>]
777
778## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after)
779## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
780## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
781## CHECK-DAG:       <<One:i\d+>>         IntConstant 1
782## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
783## CHECK-DAG:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
784## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
785## CHECK-DAG:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
786## CHECK-DAG:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
787## CHECK-DAG:                            Return [<<Add>>]
788
789## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after)
790## CHECK-NOT:                            Or
791
792# Original java source:
793#
794#     public static int $opt$noinline$notMultipleUses(int a, int b) {
795#       int tmp = ~b;
796#       return (tmp & 0x1) + (~a & tmp);
797#     }
798
799.method public static $opt$noinline$notMultipleUsesV2(II)I
800    .registers 5
801    .param p0, "a"    # I
802    .param p1, "b"    # I
803
804    .prologue
805    .line 333
806    xor-int/lit8 v0, p1, -0x1
807
808    .line 335
809    .local v0, "tmp":I
810    and-int/lit8 v1, v0, 0x1
811
812    xor-int/lit8 v2, p0, -0x1
813
814    and-int/2addr v2, v0
815
816    add-int/2addr v1, v2
817
818    return v1
819.end method
820