1 /*
2  * Copyright (C) 2018 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 RemTest {
18 
expectEquals(T expected, T result)19   public static <T extends Number> void expectEquals(T expected, T result) {
20     if (!expected.equals(result)) {
21       throw new Error("Expected: " + expected + ", found: " + result);
22     }
23   }
24 
main()25   public static void main() {
26     remInt();
27     remLong();
28   }
29 
remInt()30   private static void remInt() {
31     expectEquals(0, $noinline$IntMod2(0));
32     expectEquals(1, $noinline$IntMod2(1));
33     expectEquals(-1, $noinline$IntMod2(-1));
34     expectEquals(0, $noinline$IntMod2(2));
35     expectEquals(0, $noinline$IntMod2(-2));
36     expectEquals(1, $noinline$IntMod2(3));
37     expectEquals(-1, $noinline$IntMod2(-3));
38     expectEquals(1, $noinline$IntMod2(0x0f));
39     expectEquals(1, $noinline$IntMod2(0x00ff));
40     expectEquals(1, $noinline$IntMod2(0x00ffff));
41     expectEquals(1, $noinline$IntMod2(Integer.MAX_VALUE));
42     expectEquals(0, $noinline$IntMod2(Integer.MIN_VALUE));
43 
44     expectEquals(0, $noinline$IntModMinus2(0));
45     expectEquals(1, $noinline$IntModMinus2(1));
46     expectEquals(-1, $noinline$IntModMinus2(-1));
47     expectEquals(0, $noinline$IntModMinus2(2));
48     expectEquals(0, $noinline$IntModMinus2(-2));
49     expectEquals(1, $noinline$IntModMinus2(3));
50     expectEquals(-1, $noinline$IntModMinus2(-3));
51     expectEquals(1, $noinline$IntModMinus2(0x0f));
52     expectEquals(1, $noinline$IntModMinus2(0x00ff));
53     expectEquals(1, $noinline$IntModMinus2(0x00ffff));
54     expectEquals(1, $noinline$IntModMinus2(Integer.MAX_VALUE));
55     expectEquals(0, $noinline$IntModMinus2(Integer.MIN_VALUE));
56 
57     expectEquals(0, $noinline$IntMod16(0));
58     expectEquals(1, $noinline$IntMod16(1));
59     expectEquals(1, $noinline$IntMod16(17));
60     expectEquals(-1, $noinline$IntMod16(-1));
61     expectEquals(0, $noinline$IntMod16(32));
62     expectEquals(0, $noinline$IntMod16(-32));
63     expectEquals(0x0f, $noinline$IntMod16(0x0f));
64     expectEquals(0x0f, $noinline$IntMod16(0x00ff));
65     expectEquals(0x0f, $noinline$IntMod16(0x00ffff));
66     expectEquals(15, $noinline$IntMod16(Integer.MAX_VALUE));
67     expectEquals(0, $noinline$IntMod16(Integer.MIN_VALUE));
68 
69     expectEquals(0, $noinline$IntModMinus16(0));
70     expectEquals(1, $noinline$IntModMinus16(1));
71     expectEquals(1, $noinline$IntModMinus16(17));
72     expectEquals(-1, $noinline$IntModMinus16(-1));
73     expectEquals(0, $noinline$IntModMinus16(32));
74     expectEquals(0, $noinline$IntModMinus16(-32));
75     expectEquals(0x0f, $noinline$IntModMinus16(0x0f));
76     expectEquals(0x0f, $noinline$IntModMinus16(0x00ff));
77     expectEquals(0x0f, $noinline$IntModMinus16(0x00ffff));
78     expectEquals(15, $noinline$IntModMinus16(Integer.MAX_VALUE));
79     expectEquals(0, $noinline$IntModMinus16(Integer.MIN_VALUE));
80 
81     expectEquals(0, $noinline$IntModIntMin(0));
82     expectEquals(1, $noinline$IntModIntMin(1));
83     expectEquals(0, $noinline$IntModIntMin(Integer.MIN_VALUE));
84     expectEquals(-1, $noinline$IntModIntMin(-1));
85     expectEquals(0x0f, $noinline$IntModIntMin(0x0f));
86     expectEquals(0x00ff, $noinline$IntModIntMin(0x00ff));
87     expectEquals(0x00ffff, $noinline$IntModIntMin(0x00ffff));
88     expectEquals(Integer.MAX_VALUE, $noinline$IntModIntMin(Integer.MAX_VALUE));
89   }
90 
91   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntMod2(int) disassembly (after)
92   /// CHECK:                 cmp w{{\d+}}, #0x0
93   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x1
94   /// CHECK:                 cneg w{{\d+}}, w{{\d+}}, lt
95   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntMod2(int) disassembly (after)
96   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
97   /// CHECK-NOT:      imul
98   /// CHECK-NOT:      shr
99   /// CHECK-NOT:      imul
100   /// CHECK:          mov
101   /// CHECK:          and
102   /// CHECK:          jz/eq
103   /// CHECK:          lea
104   /// CHECK:          test
105   /// CHECK:          cmovl/nge
$noinline$IntMod2(int v)106   private static Integer $noinline$IntMod2(int v) {
107     int r = v % 2;
108     return r;
109   }
110 
111   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntModMinus2(int) disassembly (after)
112   /// CHECK:                 cmp w{{\d+}}, #0x0
113   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x1
114   /// CHECK:                 cneg w{{\d+}}, w{{\d+}}, lt
115   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntModMinus2(int) disassembly (after)
116   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
117   /// CHECK-NOT:      imul
118   /// CHECK-NOT:      shr
119   /// CHECK-NOT:      imul
120   /// CHECK:          mov
121   /// CHECK:          and
122   /// CHECK:          jz/eq
123   /// CHECK:          lea
124   /// CHECK:          test
125   /// CHECK:          cmovl/nge
$noinline$IntModMinus2(int v)126   private static Integer $noinline$IntModMinus2(int v) {
127     int r = v % -2;
128     return r;
129   }
130 
131   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntMod16(int) disassembly (after)
132   /// CHECK:                 negs w{{\d+}}, w{{\d+}}
133   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
134   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
135   /// CHECK:                 csneg w{{\d+}}, w{{\d+}}, mi
136   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntMod16(int) disassembly (after)
137   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
138   /// CHECK-NOT:      imul
139   /// CHECK-NOT:      shr
140   /// CHECK-NOT:      imul
141   /// CHECK:          mov
142   /// CHECK:          and
143   /// CHECK:          jz/eq
144   /// CHECK:          lea
145   /// CHECK:          test
146   /// CHECK:          cmovl/nge
$noinline$IntMod16(int v)147   private static Integer $noinline$IntMod16(int v) {
148     int r = v % 16;
149     return r;
150   }
151 
152   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntModMinus16(int) disassembly (after)
153   /// CHECK:                 negs w{{\d+}}, w{{\d+}}
154   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
155   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0xf
156   /// CHECK:                 csneg w{{\d+}}, w{{\d+}}, mi
157   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntModMinus16(int) disassembly (after)
158   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
159   /// CHECK-NOT:      imul
160   /// CHECK-NOT:      shr
161   /// CHECK-NOT:      imul
162   /// CHECK:          mov
163   /// CHECK:          and
164   /// CHECK:          jz/eq
165   /// CHECK:          lea
166   /// CHECK:          test
167   /// CHECK:          cmovl/nge
$noinline$IntModMinus16(int v)168   private static Integer $noinline$IntModMinus16(int v) {
169     int r = v % -16;
170     return r;
171   }
172 
173   /// CHECK-START-ARM64: java.lang.Integer RemTest.$noinline$IntModIntMin(int) disassembly (after)
174   /// CHECK:                 negs w{{\d+}}, w{{\d+}}
175   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x7fffffff
176   /// CHECK:                 and w{{\d+}}, w{{\d+}}, #0x7fffffff
177   /// CHECK:                 csneg w{{\d+}}, w{{\d+}}, mi
178   /// CHECK-START-X86_64: java.lang.Integer RemTest.$noinline$IntModIntMin(int) disassembly (after)
179   /// CHECK:          Rem [{{i\d+}},{{i\d+}}]
180   /// CHECK-NOT:      imul
181   /// CHECK-NOT:      shr
182   /// CHECK-NOT:      imul
183   /// CHECK:          mov
184   /// CHECK:          and
185   /// CHECK:          jz/eq
186   /// CHECK:          lea
187   /// CHECK:          test
188   /// CHECK:          cmovl/nge
$noinline$IntModIntMin(int v)189   private static Integer $noinline$IntModIntMin(int v) {
190     int r = v % Integer.MIN_VALUE;
191     return r;
192   }
193 
remLong()194   private static void remLong() {
195     expectEquals(0L, $noinline$LongMod2(0));
196     expectEquals(1L, $noinline$LongMod2(1));
197     expectEquals(-1L, $noinline$LongMod2(-1));
198     expectEquals(0L, $noinline$LongMod2(2));
199     expectEquals(0L, $noinline$LongMod2(-2));
200     expectEquals(1L, $noinline$LongMod2(3));
201     expectEquals(-1L, $noinline$LongMod2(-3));
202     expectEquals(1L, $noinline$LongMod2(0x0f));
203     expectEquals(1L, $noinline$LongMod2(0x00ff));
204     expectEquals(1L, $noinline$LongMod2(0x00ffff));
205     expectEquals(1L, $noinline$LongMod2(0x00ffffff));
206     expectEquals(1L, $noinline$LongMod2(0x00ffffffffL));
207     expectEquals(1L, $noinline$LongMod2(Long.MAX_VALUE));
208     expectEquals(0L, $noinline$LongMod2(Long.MIN_VALUE));
209 
210     expectEquals(0L, $noinline$LongModMinus2(0));
211     expectEquals(1L, $noinline$LongModMinus2(1));
212     expectEquals(-1L, $noinline$LongModMinus2(-1));
213     expectEquals(0L, $noinline$LongModMinus2(2));
214     expectEquals(0L, $noinline$LongModMinus2(-2));
215     expectEquals(1L, $noinline$LongModMinus2(3));
216     expectEquals(-1L, $noinline$LongModMinus2(-3));
217     expectEquals(1L, $noinline$LongModMinus2(0x0f));
218     expectEquals(1L, $noinline$LongModMinus2(0x00ff));
219     expectEquals(1L, $noinline$LongModMinus2(0x00ffff));
220     expectEquals(1L, $noinline$LongModMinus2(0x00ffffff));
221     expectEquals(1L, $noinline$LongModMinus2(0x00ffffffffL));
222     expectEquals(1L, $noinline$LongModMinus2(Long.MAX_VALUE));
223     expectEquals(0L, $noinline$LongModMinus2(Long.MIN_VALUE));
224 
225     expectEquals(0L, $noinline$LongMod16(0));
226     expectEquals(1L, $noinline$LongMod16(1));
227     expectEquals(1L, $noinline$LongMod16(17));
228     expectEquals(-1L, $noinline$LongMod16(-1));
229     expectEquals(0L, $noinline$LongMod16(32));
230     expectEquals(0L, $noinline$LongMod16(-32));
231     expectEquals(0x0fL, $noinline$LongMod16(0x0f));
232     expectEquals(0x0fL, $noinline$LongMod16(0x00ff));
233     expectEquals(0x0fL, $noinline$LongMod16(0x00ffff));
234     expectEquals(0x0fL, $noinline$LongMod16(0x00ffffff));
235     expectEquals(0x0fL, $noinline$LongMod16(0x00ffffffffL));
236     expectEquals(15L, $noinline$LongMod16(Long.MAX_VALUE));
237     expectEquals(0L, $noinline$LongMod16(Long.MIN_VALUE));
238 
239     expectEquals(0L, $noinline$LongModMinus16(0));
240     expectEquals(1L, $noinline$LongModMinus16(1));
241     expectEquals(1L, $noinline$LongModMinus16(17));
242     expectEquals(-1L, $noinline$LongModMinus16(-1));
243     expectEquals(0L, $noinline$LongModMinus16(32));
244     expectEquals(0L, $noinline$LongModMinus16(-32));
245     expectEquals(0x0fL, $noinline$LongModMinus16(0x0f));
246     expectEquals(0x0fL, $noinline$LongModMinus16(0x00ff));
247     expectEquals(0x0fL, $noinline$LongModMinus16(0x00ffff));
248     expectEquals(0x0fL, $noinline$LongModMinus16(0x00ffffff));
249     expectEquals(0x0fL, $noinline$LongModMinus16(0x00ffffffffL));
250     expectEquals(15L, $noinline$LongModMinus16(Long.MAX_VALUE));
251     expectEquals(0L, $noinline$LongModMinus16(Long.MIN_VALUE));
252 
253     expectEquals(0L, $noinline$LongModLongMin(0));
254     expectEquals(1L, $noinline$LongModLongMin(1));
255     expectEquals(0L, $noinline$LongModLongMin(Long.MIN_VALUE));
256     expectEquals(-1L, $noinline$LongModLongMin(-1));
257     expectEquals(0x0fL, $noinline$LongModLongMin(0x0f));
258     expectEquals(0x00ffL, $noinline$LongModLongMin(0x00ff));
259     expectEquals(0x00ffffL, $noinline$LongModLongMin(0x00ffff));
260     expectEquals(0x00ffffffL, $noinline$LongModLongMin(0x00ffffff));
261     expectEquals(0x00ffffffffL, $noinline$LongModLongMin(0x00ffffffffL));
262     expectEquals(Long.MAX_VALUE, $noinline$LongModLongMin(Long.MAX_VALUE));
263   }
264 
265   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongMod2(long) disassembly (after)
266   /// CHECK:                 cmp x{{\d+}}, #0x0
267   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x1
268   /// CHECK:                 cneg x{{\d+}}, x{{\d+}}, lt
269   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongMod2(long) disassembly (after)
270   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
271   /// CHECK-NOT:      imul
272   /// CHECK-NOT:      shrq
273   /// CHECK-NOT:      imulq
274   /// CHECK:          movq
275   /// CHECK:          andq
276   /// CHECK:          jz/eq
277   /// CHECK:          movq
278   /// CHECK:          sarq
279   /// CHECK:          shlq
280   /// CHECK:          orq
$noinline$LongMod2(long v)281   private static Long $noinline$LongMod2(long v) {
282     long r = v % 2;
283     return r;
284   }
285 
286   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongModMinus2(long) disassembly (after)
287   /// CHECK:                 cmp x{{\d+}}, #0x0
288   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x1
289   /// CHECK:                 cneg x{{\d+}}, x{{\d+}}, lt
290   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongModMinus2(long) disassembly (after)
291   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
292   /// CHECK-NOT:      imul
293   /// CHECK-NOT:      shrq
294   /// CHECK-NOT:      imulq
295   /// CHECK:          movq
296   /// CHECK:          andq
297   /// CHECK:          jz/eq
298   /// CHECK:          movq
299   /// CHECK:          sarq
300   /// CHECK:          shlq
301   /// CHECK:          orq
$noinline$LongModMinus2(long v)302   private static Long $noinline$LongModMinus2(long v) {
303     long r = v % -2;
304     return r;
305   }
306 
307   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongMod16(long) disassembly (after)
308   /// CHECK:                 negs x{{\d+}}, x{{\d+}}
309   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
310   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
311   /// CHECK:                 csneg x{{\d+}}, x{{\d+}}, mi
312 
313   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongMod16(long) disassembly (after)
314   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
315   /// CHECK-NOT:      imul
316   /// CHECK-NOT:      shrq
317   /// CHECK-NOT:      imulq
318   /// CHECK:          movq
319   /// CHECK:          andq
320   /// CHECK:          jz/eq
321   /// CHECK:          movq
322   /// CHECK:          sarq
323   /// CHECK:          shlq
324   /// CHECK:          orq
$noinline$LongMod16(long v)325   private static Long $noinline$LongMod16(long v) {
326     long r = v % 16;
327     return r;
328   }
329 
330   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongModMinus16(long) disassembly (after)
331   /// CHECK:                 negs x{{\d+}}, x{{\d+}}
332   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
333   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0xf
334   /// CHECK:                 csneg x{{\d+}}, x{{\d+}}, mi
335   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongModMinus16(long) disassembly (after)
336   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
337   /// CHECK-NOT:      imul
338   /// CHECK-NOT:      shrq
339   /// CHECK-NOT:      imulq
340   /// CHECK:          movq
341   /// CHECK:          andq
342   /// CHECK:          jz/eq
343   /// CHECK:          movq
344   /// CHECK:          sarq
345   /// CHECK:          shlq
346   /// CHECK:          orq
$noinline$LongModMinus16(long v)347   private static Long $noinline$LongModMinus16(long v) {
348     long r = v % -16;
349     return r;
350   }
351 
352   /// CHECK-START-ARM64: java.lang.Long RemTest.$noinline$LongModLongMin(long) disassembly (after)
353   /// CHECK:                 negs x{{\d+}}, x{{\d+}}
354   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x7fffffffffffffff
355   /// CHECK:                 and x{{\d+}}, x{{\d+}}, #0x7fffffffffffffff
356   /// CHECK:                 csneg x{{\d+}}, x{{\d+}}, mi
357   /// CHECK-START-X86_64: java.lang.Long RemTest.$noinline$LongModLongMin(long) disassembly (after)
358   /// CHECK:          Rem [{{j\d+}},{{j\d+}}]
359   /// CHECK-NOT:      imul
360   /// CHECK-NOT:      shrq
361   /// CHECK-NOT:      imulq
362   /// CHECK:          movq
363   /// CHECK:          andq
364   /// CHECK:          jz/eq
365   /// CHECK:          movq
366   /// CHECK:          sarq
367   /// CHECK:          shlq
368   /// CHECK:          orq
$noinline$LongModLongMin(long v)369   private static Long $noinline$LongModLongMin(long v) {
370     long r = v % Long.MIN_VALUE;
371     return r;
372   }
373 }
374