blob: c51eda8a66c90d2b8bfc8af64a47fb39dcf8c5f0 [file] [log] [blame]
Alexandre Ramesca0e3a02016-02-03 10:54:07 +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 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).
Alexandre Ramesa211a022016-02-04 13:16:08 +000040 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000041 /// 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
Alexandre Ramesa211a022016-02-04 13:16:08 +000049 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000050 /// 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
Alexandre Ramesa211a022016-02-04 13:16:08 +000056 /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000057 /// CHECK: Not
58 /// CHECK-NOT: Not
59 /// CHECK-NOT: And
60
61 public static int $opt$noinline$andToOr(int a, int b) {
62 if (doThrow) throw new Error();
63 return ~a & ~b;
64 }
65
66 /**
67 * Test transformation of Not/Not/Or into And/Not.
68 */
69
70 // See note above.
71 // The second Xor has its arguments reversed for no obvious reason.
Alexandre Ramesa211a022016-02-04 13:16:08 +000072 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000073 /// CHECK: <<P1:j\d+>> ParameterValue
74 /// CHECK: <<P2:j\d+>> ParameterValue
75 /// CHECK: <<CstM1:j\d+>> LongConstant -1
76 /// CHECK: <<Not1:j\d+>> Xor [<<P1>>,<<CstM1>>]
77 /// CHECK: <<Not2:j\d+>> Xor [<<CstM1>>,<<P2>>]
78 /// CHECK: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>]
79 /// CHECK: Return [<<Or>>]
80
Alexandre Ramesa211a022016-02-04 13:16:08 +000081 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000082 /// CHECK: <<P1:j\d+>> ParameterValue
83 /// CHECK: <<P2:j\d+>> ParameterValue
84 /// CHECK: <<And:j\d+>> And [<<P1>>,<<P2>>]
85 /// CHECK: <<Not:j\d+>> Not [<<And>>]
86 /// CHECK: Return [<<Not>>]
87
Alexandre Ramesa211a022016-02-04 13:16:08 +000088 /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +000089 /// CHECK: Not
90 /// CHECK-NOT: Not
91 /// CHECK-NOT: Or
92
93 public static long $opt$noinline$orToAnd(long a, long b) {
94 if (doThrow) throw new Error();
95 return ~a | ~b;
96 }
97
98 /**
99 * Test that the transformation copes with inputs being separated from the
100 * bitwise operations.
101 * This is a regression test. The initial logic was inserting the new bitwise
102 * operation incorrectly.
103 */
104
Alexandre Ramesa211a022016-02-04 13:16:08 +0000105 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000106 /// CHECK: <<P1:i\d+>> ParameterValue
107 /// CHECK: <<P2:i\d+>> ParameterValue
108 /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
109 /// CHECK-DAG: <<CstM1:i\d+>> IntConstant -1
110 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
111 /// CHECK: <<Not1:i\d+>> Xor [<<AddP1>>,<<CstM1>>]
112 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
113 /// CHECK: <<Not2:i\d+>> Xor [<<AddP2>>,<<CstM1>>]
114 /// CHECK: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>]
115 /// CHECK: Return [<<Or>>]
116
Alexandre Ramesa211a022016-02-04 13:16:08 +0000117 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000118 /// CHECK: <<P1:i\d+>> ParameterValue
119 /// CHECK: <<P2:i\d+>> ParameterValue
120 /// CHECK: <<Cst1:i\d+>> IntConstant 1
121 /// CHECK: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
122 /// CHECK: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
123 /// CHECK: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>]
124 /// CHECK: <<Not:i\d+>> Not [<<And>>]
125 /// CHECK: Return [<<Not>>]
126
Alexandre Ramesa211a022016-02-04 13:16:08 +0000127 /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000128 /// CHECK: Not
129 /// CHECK-NOT: Not
130 /// CHECK-NOT: Or
131
132 public static int $opt$noinline$regressInputsAway(int a, int b) {
133 if (doThrow) throw new Error();
134 int a1 = a + 1;
135 int not_a1 = ~a1;
136 int b1 = b + 1;
137 int not_b1 = ~b1;
138 return not_a1 | not_b1;
139 }
140
141 /**
142 * Test transformation of Not/Not/Xor into Xor.
143 */
144
145 // See first note above.
Alexandre Ramesa211a022016-02-04 13:16:08 +0000146 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000147 /// CHECK: <<P1:i\d+>> ParameterValue
148 /// CHECK: <<P2:i\d+>> ParameterValue
149 /// CHECK: <<CstM1:i\d+>> IntConstant -1
150 /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
151 /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
152 /// CHECK: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>]
153 /// CHECK: Return [<<Xor>>]
154
Alexandre Ramesa211a022016-02-04 13:16:08 +0000155 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000156 /// CHECK: <<P1:i\d+>> ParameterValue
157 /// CHECK: <<P2:i\d+>> ParameterValue
158 /// CHECK: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>]
159 /// CHECK: Return [<<Xor>>]
160
Alexandre Ramesa211a022016-02-04 13:16:08 +0000161 /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000162 /// CHECK-NOT: Not
163
164 public static int $opt$noinline$notXorToXor(int a, int b) {
165 if (doThrow) throw new Error();
166 return ~a ^ ~b;
167 }
168
169 /**
170 * Check that no transformation is done when one Not has multiple uses.
171 */
172
Alexandre Ramesa211a022016-02-04 13:16:08 +0000173 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000174 /// CHECK: <<P1:i\d+>> ParameterValue
175 /// CHECK: <<P2:i\d+>> ParameterValue
176 /// CHECK: <<CstM1:i\d+>> IntConstant -1
177 /// CHECK: <<One:i\d+>> IntConstant 1
178 /// CHECK: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
179 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
180 /// CHECK: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
181 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
182 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
183 /// CHECK: Return [<<Add>>]
184
Alexandre Ramesa211a022016-02-04 13:16:08 +0000185 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000186 /// CHECK: <<P1:i\d+>> ParameterValue
187 /// CHECK: <<P2:i\d+>> ParameterValue
188 /// CHECK: <<One:i\d+>> IntConstant 1
189 /// CHECK: <<Not2:i\d+>> Not [<<P2>>]
190 /// CHECK: <<And2:i\d+>> And [<<Not2>>,<<One>>]
191 /// CHECK: <<Not1:i\d+>> Not [<<P1>>]
192 /// CHECK: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
193 /// CHECK: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
194 /// CHECK: Return [<<Add>>]
195
Alexandre Ramesa211a022016-02-04 13:16:08 +0000196 /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
Alexandre Ramesca0e3a02016-02-03 10:54:07 +0000197 /// CHECK-NOT: Or
198
199 public static int $opt$noinline$notMultipleUses(int a, int b) {
200 if (doThrow) throw new Error();
201 int tmp = ~b;
202 return (tmp & 0x1) + (~a & tmp);
203 }
204
205 public static void main(String[] args) {
206 assertIntEquals(~0xff, $opt$noinline$andToOr(0xf, 0xff));
207 assertLongEquals(~0xf, $opt$noinline$orToAnd(0xf, 0xff));
208 assertIntEquals(0xf0, $opt$noinline$notXorToXor(0xf, 0xff));
209 assertIntEquals(~0xff, $opt$noinline$notMultipleUses(0xf, 0xff));
210 }
211}