• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Tests arithmetic expressions
6
7package main
8
9import (
10	"math"
11	"runtime"
12	"testing"
13)
14
15const (
16	y = 0x0fffFFFF
17)
18
19var (
20	g8  int8
21	g16 int16
22	g32 int32
23	g64 int64
24)
25
26//go:noinline
27func lshNop1(x uint64) uint64 {
28	// two outer shifts should be removed
29	return (((x << 5) >> 2) << 2)
30}
31
32//go:noinline
33func lshNop2(x uint64) uint64 {
34	return (((x << 5) >> 2) << 3)
35}
36
37//go:noinline
38func lshNop3(x uint64) uint64 {
39	return (((x << 5) >> 2) << 6)
40}
41
42//go:noinline
43func lshNotNop(x uint64) uint64 {
44	// outer shift can't be removed
45	return (((x << 5) >> 2) << 1)
46}
47
48//go:noinline
49func rshNop1(x uint64) uint64 {
50	return (((x >> 5) << 2) >> 2)
51}
52
53//go:noinline
54func rshNop2(x uint64) uint64 {
55	return (((x >> 5) << 2) >> 3)
56}
57
58//go:noinline
59func rshNop3(x uint64) uint64 {
60	return (((x >> 5) << 2) >> 6)
61}
62
63//go:noinline
64func rshNotNop(x uint64) uint64 {
65	return (((x >> 5) << 2) >> 1)
66}
67
68func testShiftRemoval(t *testing.T) {
69	allSet := ^uint64(0)
70	if want, got := uint64(0x7ffffffffffffff), rshNop1(allSet); want != got {
71		t.Errorf("testShiftRemoval rshNop1 failed, wanted %d got %d", want, got)
72	}
73	if want, got := uint64(0x3ffffffffffffff), rshNop2(allSet); want != got {
74		t.Errorf("testShiftRemoval rshNop2 failed, wanted %d got %d", want, got)
75	}
76	if want, got := uint64(0x7fffffffffffff), rshNop3(allSet); want != got {
77		t.Errorf("testShiftRemoval rshNop3 failed, wanted %d got %d", want, got)
78	}
79	if want, got := uint64(0xffffffffffffffe), rshNotNop(allSet); want != got {
80		t.Errorf("testShiftRemoval rshNotNop failed, wanted %d got %d", want, got)
81	}
82	if want, got := uint64(0xffffffffffffffe0), lshNop1(allSet); want != got {
83		t.Errorf("testShiftRemoval lshNop1 failed, wanted %d got %d", want, got)
84	}
85	if want, got := uint64(0xffffffffffffffc0), lshNop2(allSet); want != got {
86		t.Errorf("testShiftRemoval lshNop2 failed, wanted %d got %d", want, got)
87	}
88	if want, got := uint64(0xfffffffffffffe00), lshNop3(allSet); want != got {
89		t.Errorf("testShiftRemoval lshNop3 failed, wanted %d got %d", want, got)
90	}
91	if want, got := uint64(0x7ffffffffffffff0), lshNotNop(allSet); want != got {
92		t.Errorf("testShiftRemoval lshNotNop failed, wanted %d got %d", want, got)
93	}
94}
95
96//go:noinline
97func parseLE64(b []byte) uint64 {
98	// skip the first two bytes, and parse the remaining 8 as a uint64
99	return uint64(b[2]) | uint64(b[3])<<8 | uint64(b[4])<<16 | uint64(b[5])<<24 |
100		uint64(b[6])<<32 | uint64(b[7])<<40 | uint64(b[8])<<48 | uint64(b[9])<<56
101}
102
103//go:noinline
104func parseLE32(b []byte) uint32 {
105	return uint32(b[2]) | uint32(b[3])<<8 | uint32(b[4])<<16 | uint32(b[5])<<24
106}
107
108//go:noinline
109func parseLE16(b []byte) uint16 {
110	return uint16(b[2]) | uint16(b[3])<<8
111}
112
113// testLoadCombine tests for issue #14694 where load combining didn't respect the pointer offset.
114func testLoadCombine(t *testing.T) {
115	testData := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}
116	if want, got := uint64(0x0908070605040302), parseLE64(testData); want != got {
117		t.Errorf("testLoadCombine failed, wanted %d got %d", want, got)
118	}
119	if want, got := uint32(0x05040302), parseLE32(testData); want != got {
120		t.Errorf("testLoadCombine failed, wanted %d got %d", want, got)
121	}
122	if want, got := uint16(0x0302), parseLE16(testData); want != got {
123		t.Errorf("testLoadCombine failed, wanted %d got %d", want, got)
124	}
125}
126
127var loadSymData = [...]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
128
129func testLoadSymCombine(t *testing.T) {
130	w2 := uint16(0x0201)
131	g2 := uint16(loadSymData[0]) | uint16(loadSymData[1])<<8
132	if g2 != w2 {
133		t.Errorf("testLoadSymCombine failed, wanted %d got %d", w2, g2)
134	}
135	w4 := uint32(0x04030201)
136	g4 := uint32(loadSymData[0]) | uint32(loadSymData[1])<<8 |
137		uint32(loadSymData[2])<<16 | uint32(loadSymData[3])<<24
138	if g4 != w4 {
139		t.Errorf("testLoadSymCombine failed, wanted %d got %d", w4, g4)
140	}
141	w8 := uint64(0x0807060504030201)
142	g8 := uint64(loadSymData[0]) | uint64(loadSymData[1])<<8 |
143		uint64(loadSymData[2])<<16 | uint64(loadSymData[3])<<24 |
144		uint64(loadSymData[4])<<32 | uint64(loadSymData[5])<<40 |
145		uint64(loadSymData[6])<<48 | uint64(loadSymData[7])<<56
146	if g8 != w8 {
147		t.Errorf("testLoadSymCombine failed, wanted %d got %d", w8, g8)
148	}
149}
150
151//go:noinline
152func invalidAdd_ssa(x uint32) uint32 {
153	return x + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y
154}
155
156//go:noinline
157func invalidSub_ssa(x uint32) uint32 {
158	return x - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y
159}
160
161//go:noinline
162func invalidMul_ssa(x uint32) uint32 {
163	return x * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y
164}
165
166// testLargeConst tests a situation where larger than 32 bit consts were passed to ADDL
167// causing an invalid instruction error.
168func testLargeConst(t *testing.T) {
169	if want, got := uint32(268435440), invalidAdd_ssa(1); want != got {
170		t.Errorf("testLargeConst add failed, wanted %d got %d", want, got)
171	}
172	if want, got := uint32(4026531858), invalidSub_ssa(1); want != got {
173		t.Errorf("testLargeConst sub failed, wanted %d got %d", want, got)
174	}
175	if want, got := uint32(268435455), invalidMul_ssa(1); want != got {
176		t.Errorf("testLargeConst mul failed, wanted %d got %d", want, got)
177	}
178}
179
180// testArithRshConst ensures that "const >> const" right shifts correctly perform
181// sign extension on the lhs constant
182func testArithRshConst(t *testing.T) {
183	wantu := uint64(0x4000000000000000)
184	if got := arithRshuConst_ssa(); got != wantu {
185		t.Errorf("arithRshuConst failed, wanted %d got %d", wantu, got)
186	}
187
188	wants := int64(-0x4000000000000000)
189	if got := arithRshConst_ssa(); got != wants {
190		t.Errorf("arithRshConst failed, wanted %d got %d", wants, got)
191	}
192}
193
194//go:noinline
195func arithRshuConst_ssa() uint64 {
196	y := uint64(0x8000000000000001)
197	z := uint64(1)
198	return uint64(y >> z)
199}
200
201//go:noinline
202func arithRshConst_ssa() int64 {
203	y := int64(-0x8000000000000000)
204	z := uint64(1)
205	return int64(y >> z)
206}
207
208//go:noinline
209func arithConstShift_ssa(x int64) int64 {
210	return x >> 100
211}
212
213// testArithConstShift tests that right shift by large constants preserve
214// the sign of the input.
215func testArithConstShift(t *testing.T) {
216	want := int64(-1)
217	if got := arithConstShift_ssa(-1); want != got {
218		t.Errorf("arithConstShift_ssa(-1) failed, wanted %d got %d", want, got)
219	}
220	want = 0
221	if got := arithConstShift_ssa(1); want != got {
222		t.Errorf("arithConstShift_ssa(1) failed, wanted %d got %d", want, got)
223	}
224}
225
226// overflowConstShift_ssa verifies that constant folding for shift
227// doesn't wrap (i.e. x << MAX_INT << 1 doesn't get folded to x << 0).
228//
229//go:noinline
230func overflowConstShift64_ssa(x int64) int64 {
231	return x << uint64(0xffffffffffffffff) << uint64(1)
232}
233
234//go:noinline
235func overflowConstShift32_ssa(x int64) int32 {
236	return int32(x) << uint32(0xffffffff) << uint32(1)
237}
238
239//go:noinline
240func overflowConstShift16_ssa(x int64) int16 {
241	return int16(x) << uint16(0xffff) << uint16(1)
242}
243
244//go:noinline
245func overflowConstShift8_ssa(x int64) int8 {
246	return int8(x) << uint8(0xff) << uint8(1)
247}
248
249func testOverflowConstShift(t *testing.T) {
250	want := int64(0)
251	for x := int64(-127); x < int64(127); x++ {
252		got := overflowConstShift64_ssa(x)
253		if want != got {
254			t.Errorf("overflowShift64 failed, wanted %d got %d", want, got)
255		}
256		got = int64(overflowConstShift32_ssa(x))
257		if want != got {
258			t.Errorf("overflowShift32 failed, wanted %d got %d", want, got)
259		}
260		got = int64(overflowConstShift16_ssa(x))
261		if want != got {
262			t.Errorf("overflowShift16 failed, wanted %d got %d", want, got)
263		}
264		got = int64(overflowConstShift8_ssa(x))
265		if want != got {
266			t.Errorf("overflowShift8 failed, wanted %d got %d", want, got)
267		}
268	}
269}
270
271//go:noinline
272func rsh64x64ConstOverflow8(x int8) int64 {
273	return int64(x) >> 9
274}
275
276//go:noinline
277func rsh64x64ConstOverflow16(x int16) int64 {
278	return int64(x) >> 17
279}
280
281//go:noinline
282func rsh64x64ConstOverflow32(x int32) int64 {
283	return int64(x) >> 33
284}
285
286func testArithRightShiftConstOverflow(t *testing.T) {
287	allSet := int64(-1)
288	if got, want := rsh64x64ConstOverflow8(0x7f), int64(0); got != want {
289		t.Errorf("rsh64x64ConstOverflow8 failed: got %v, want %v", got, want)
290	}
291	if got, want := rsh64x64ConstOverflow16(0x7fff), int64(0); got != want {
292		t.Errorf("rsh64x64ConstOverflow16 failed: got %v, want %v", got, want)
293	}
294	if got, want := rsh64x64ConstOverflow32(0x7ffffff), int64(0); got != want {
295		t.Errorf("rsh64x64ConstOverflow32 failed: got %v, want %v", got, want)
296	}
297	if got, want := rsh64x64ConstOverflow8(int8(-1)), allSet; got != want {
298		t.Errorf("rsh64x64ConstOverflow8 failed: got %v, want %v", got, want)
299	}
300	if got, want := rsh64x64ConstOverflow16(int16(-1)), allSet; got != want {
301		t.Errorf("rsh64x64ConstOverflow16 failed: got %v, want %v", got, want)
302	}
303	if got, want := rsh64x64ConstOverflow32(int32(-1)), allSet; got != want {
304		t.Errorf("rsh64x64ConstOverflow32 failed: got %v, want %v", got, want)
305	}
306}
307
308//go:noinline
309func rsh64Ux64ConstOverflow8(x uint8) uint64 {
310	return uint64(x) >> 9
311}
312
313//go:noinline
314func rsh64Ux64ConstOverflow16(x uint16) uint64 {
315	return uint64(x) >> 17
316}
317
318//go:noinline
319func rsh64Ux64ConstOverflow32(x uint32) uint64 {
320	return uint64(x) >> 33
321}
322
323func testRightShiftConstOverflow(t *testing.T) {
324	if got, want := rsh64Ux64ConstOverflow8(0xff), uint64(0); got != want {
325		t.Errorf("rsh64Ux64ConstOverflow8 failed: got %v, want %v", got, want)
326	}
327	if got, want := rsh64Ux64ConstOverflow16(0xffff), uint64(0); got != want {
328		t.Errorf("rsh64Ux64ConstOverflow16 failed: got %v, want %v", got, want)
329	}
330	if got, want := rsh64Ux64ConstOverflow32(0xffffffff), uint64(0); got != want {
331		t.Errorf("rsh64Ux64ConstOverflow32 failed: got %v, want %v", got, want)
332	}
333}
334
335// test64BitConstMult tests that rewrite rules don't fold 64 bit constants
336// into multiply instructions.
337func test64BitConstMult(t *testing.T) {
338	want := int64(103079215109)
339	if got := test64BitConstMult_ssa(1, 2); want != got {
340		t.Errorf("test64BitConstMult failed, wanted %d got %d", want, got)
341	}
342}
343
344//go:noinline
345func test64BitConstMult_ssa(a, b int64) int64 {
346	return 34359738369*a + b*34359738370
347}
348
349// test64BitConstAdd tests that rewrite rules don't fold 64 bit constants
350// into add instructions.
351func test64BitConstAdd(t *testing.T) {
352	want := int64(3567671782835376650)
353	if got := test64BitConstAdd_ssa(1, 2); want != got {
354		t.Errorf("test64BitConstAdd failed, wanted %d got %d", want, got)
355	}
356}
357
358//go:noinline
359func test64BitConstAdd_ssa(a, b int64) int64 {
360	return a + 575815584948629622 + b + 2991856197886747025
361}
362
363// testRegallocCVSpill tests that regalloc spills a value whose last use is the
364// current value.
365func testRegallocCVSpill(t *testing.T) {
366	want := int8(-9)
367	if got := testRegallocCVSpill_ssa(1, 2, 3, 4); want != got {
368		t.Errorf("testRegallocCVSpill failed, wanted %d got %d", want, got)
369	}
370}
371
372//go:noinline
373func testRegallocCVSpill_ssa(a, b, c, d int8) int8 {
374	return a + -32 + b + 63*c*-87*d
375}
376
377func testBitwiseLogic(t *testing.T) {
378	a, b := uint32(57623283), uint32(1314713839)
379	if want, got := uint32(38551779), testBitwiseAnd_ssa(a, b); want != got {
380		t.Errorf("testBitwiseAnd failed, wanted %d got %d", want, got)
381	}
382	if want, got := uint32(1333785343), testBitwiseOr_ssa(a, b); want != got {
383		t.Errorf("testBitwiseOr failed, wanted %d got %d", want, got)
384	}
385	if want, got := uint32(1295233564), testBitwiseXor_ssa(a, b); want != got {
386		t.Errorf("testBitwiseXor failed, wanted %d got %d", want, got)
387	}
388	if want, got := int32(832), testBitwiseLsh_ssa(13, 4, 2); want != got {
389		t.Errorf("testBitwiseLsh failed, wanted %d got %d", want, got)
390	}
391	if want, got := int32(0), testBitwiseLsh_ssa(13, 25, 15); want != got {
392		t.Errorf("testBitwiseLsh failed, wanted %d got %d", want, got)
393	}
394	if want, got := int32(0), testBitwiseLsh_ssa(-13, 25, 15); want != got {
395		t.Errorf("testBitwiseLsh failed, wanted %d got %d", want, got)
396	}
397	if want, got := int32(-13), testBitwiseRsh_ssa(-832, 4, 2); want != got {
398		t.Errorf("testBitwiseRsh failed, wanted %d got %d", want, got)
399	}
400	if want, got := int32(0), testBitwiseRsh_ssa(13, 25, 15); want != got {
401		t.Errorf("testBitwiseRsh failed, wanted %d got %d", want, got)
402	}
403	if want, got := int32(-1), testBitwiseRsh_ssa(-13, 25, 15); want != got {
404		t.Errorf("testBitwiseRsh failed, wanted %d got %d", want, got)
405	}
406	if want, got := uint32(0x3ffffff), testBitwiseRshU_ssa(0xffffffff, 4, 2); want != got {
407		t.Errorf("testBitwiseRshU failed, wanted %d got %d", want, got)
408	}
409	if want, got := uint32(0), testBitwiseRshU_ssa(13, 25, 15); want != got {
410		t.Errorf("testBitwiseRshU failed, wanted %d got %d", want, got)
411	}
412	if want, got := uint32(0), testBitwiseRshU_ssa(0x8aaaaaaa, 25, 15); want != got {
413		t.Errorf("testBitwiseRshU failed, wanted %d got %d", want, got)
414	}
415}
416
417//go:noinline
418func testBitwiseAnd_ssa(a, b uint32) uint32 {
419	return a & b
420}
421
422//go:noinline
423func testBitwiseOr_ssa(a, b uint32) uint32 {
424	return a | b
425}
426
427//go:noinline
428func testBitwiseXor_ssa(a, b uint32) uint32 {
429	return a ^ b
430}
431
432//go:noinline
433func testBitwiseLsh_ssa(a int32, b, c uint32) int32 {
434	return a << b << c
435}
436
437//go:noinline
438func testBitwiseRsh_ssa(a int32, b, c uint32) int32 {
439	return a >> b >> c
440}
441
442//go:noinline
443func testBitwiseRshU_ssa(a uint32, b, c uint32) uint32 {
444	return a >> b >> c
445}
446
447//go:noinline
448func testShiftCX_ssa() int {
449	v1 := uint8(3)
450	v4 := (v1 * v1) ^ v1 | v1 - v1 - v1&v1 ^ uint8(3+2) + v1*1>>0 - v1 | 1 | v1<<(2*3|0-0*0^1)
451	v5 := v4>>(3-0-uint(3)) | v1 | v1 + v1 ^ v4<<(0+1|3&1)<<(uint64(1)<<0*2*0<<0) ^ v1
452	v6 := v5 ^ (v1+v1)*v1 | v1 | v1*v1>>(v1&v1)>>(uint(1)<<0*uint(3)>>1)*v1<<2*v1<<v1 - v1>>2 | (v4 - v1) ^ v1 + v1 ^ v1>>1 | v1 + v1 - v1 ^ v1
453	v7 := v6 & v5 << 0
454	v1++
455	v11 := 2&1 ^ 0 + 3 | int(0^0)<<1>>(1*0*3) ^ 0*0 ^ 3&0*3&3 ^ 3*3 ^ 1 ^ int(2)<<(2*3) + 2 | 2 | 2 ^ 2 + 1 | 3 | 0 ^ int(1)>>1 ^ 2 // int
456	v7--
457	return int(uint64(2*1)<<(3-2)<<uint(3>>v7)-2)&v11 | v11 - int(2)<<0>>(2-1)*(v11*0&v11<<1<<(uint8(2)+v4))
458}
459
460func testShiftCX(t *testing.T) {
461	want := 141
462	if got := testShiftCX_ssa(); want != got {
463		t.Errorf("testShiftCX failed, wanted %d got %d", want, got)
464	}
465}
466
467// testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly.
468func testSubqToNegq(t *testing.T) {
469	want := int64(-318294940372190156)
470	if got := testSubqToNegq_ssa(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2); want != got {
471		t.Errorf("testSubqToNegq failed, wanted %d got %d", want, got)
472	}
473}
474
475//go:noinline
476func testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k int64) int64 {
477	return a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479
478}
479
480func testOcom(t *testing.T) {
481	want1, want2 := int32(0x55555555), int32(-0x55555556)
482	if got1, got2 := testOcom_ssa(0x55555555, 0x55555555); want1 != got1 || want2 != got2 {
483		t.Errorf("testOcom failed, wanted %d and %d got %d and %d", want1, want2, got1, got2)
484	}
485}
486
487//go:noinline
488func testOcom_ssa(a, b int32) (int32, int32) {
489	return ^^^^a, ^^^^^b
490}
491
492func lrot1_ssa(w uint8, x uint16, y uint32, z uint64) (a uint8, b uint16, c uint32, d uint64) {
493	a = (w << 5) | (w >> 3)
494	b = (x << 13) | (x >> 3)
495	c = (y << 29) | (y >> 3)
496	d = (z << 61) | (z >> 3)
497	return
498}
499
500//go:noinline
501func lrot2_ssa(w, n uint32) uint32 {
502	// Want to be sure that a "rotate by 32" which
503	// is really 0 | (w >> 0) == w
504	// is correctly compiled.
505	return (w << n) | (w >> (32 - n))
506}
507
508//go:noinline
509func lrot3_ssa(w uint32) uint32 {
510	// Want to be sure that a "rotate by 32" which
511	// is really 0 | (w >> 0) == w
512	// is correctly compiled.
513	return (w << 32) | (w >> (32 - 32))
514}
515
516func testLrot(t *testing.T) {
517	wantA, wantB, wantC, wantD := uint8(0xe1), uint16(0xe001),
518		uint32(0xe0000001), uint64(0xe000000000000001)
519	a, b, c, d := lrot1_ssa(0xf, 0xf, 0xf, 0xf)
520	if a != wantA || b != wantB || c != wantC || d != wantD {
521		t.Errorf("lrot1_ssa(0xf, 0xf, 0xf, 0xf)=%d %d %d %d, got %d %d %d %d", wantA, wantB, wantC, wantD, a, b, c, d)
522	}
523	x := lrot2_ssa(0xb0000001, 32)
524	wantX := uint32(0xb0000001)
525	if x != wantX {
526		t.Errorf("lrot2_ssa(0xb0000001, 32)=%d, got %d", wantX, x)
527	}
528	x = lrot3_ssa(0xb0000001)
529	if x != wantX {
530		t.Errorf("lrot3_ssa(0xb0000001)=%d, got %d", wantX, x)
531	}
532
533}
534
535//go:noinline
536func sub1_ssa() uint64 {
537	v1 := uint64(3) // uint64
538	return v1*v1 - (v1&v1)&v1
539}
540
541//go:noinline
542func sub2_ssa() uint8 {
543	v1 := uint8(0)
544	v3 := v1 + v1 + v1 ^ v1 | 3 + v1 ^ v1 | v1 ^ v1
545	v1-- // dev.ssa doesn't see this one
546	return v1 ^ v1*v1 - v3
547}
548
549func testSubConst(t *testing.T) {
550	x1 := sub1_ssa()
551	want1 := uint64(6)
552	if x1 != want1 {
553		t.Errorf("sub1_ssa()=%d, got %d", want1, x1)
554	}
555	x2 := sub2_ssa()
556	want2 := uint8(251)
557	if x2 != want2 {
558		t.Errorf("sub2_ssa()=%d, got %d", want2, x2)
559	}
560}
561
562//go:noinline
563func orPhi_ssa(a bool, x int) int {
564	v := 0
565	if a {
566		v = -1
567	} else {
568		v = -1
569	}
570	return x | v
571}
572
573func testOrPhi(t *testing.T) {
574	if want, got := -1, orPhi_ssa(true, 4); got != want {
575		t.Errorf("orPhi_ssa(true, 4)=%d, want %d", got, want)
576	}
577	if want, got := -1, orPhi_ssa(false, 0); got != want {
578		t.Errorf("orPhi_ssa(false, 0)=%d, want %d", got, want)
579	}
580}
581
582//go:noinline
583func addshiftLL_ssa(a, b uint32) uint32 {
584	return a + b<<3
585}
586
587//go:noinline
588func subshiftLL_ssa(a, b uint32) uint32 {
589	return a - b<<3
590}
591
592//go:noinline
593func rsbshiftLL_ssa(a, b uint32) uint32 {
594	return a<<3 - b
595}
596
597//go:noinline
598func andshiftLL_ssa(a, b uint32) uint32 {
599	return a & (b << 3)
600}
601
602//go:noinline
603func orshiftLL_ssa(a, b uint32) uint32 {
604	return a | b<<3
605}
606
607//go:noinline
608func xorshiftLL_ssa(a, b uint32) uint32 {
609	return a ^ b<<3
610}
611
612//go:noinline
613func bicshiftLL_ssa(a, b uint32) uint32 {
614	return a &^ (b << 3)
615}
616
617//go:noinline
618func notshiftLL_ssa(a uint32) uint32 {
619	return ^(a << 3)
620}
621
622//go:noinline
623func addshiftRL_ssa(a, b uint32) uint32 {
624	return a + b>>3
625}
626
627//go:noinline
628func subshiftRL_ssa(a, b uint32) uint32 {
629	return a - b>>3
630}
631
632//go:noinline
633func rsbshiftRL_ssa(a, b uint32) uint32 {
634	return a>>3 - b
635}
636
637//go:noinline
638func andshiftRL_ssa(a, b uint32) uint32 {
639	return a & (b >> 3)
640}
641
642//go:noinline
643func orshiftRL_ssa(a, b uint32) uint32 {
644	return a | b>>3
645}
646
647//go:noinline
648func xorshiftRL_ssa(a, b uint32) uint32 {
649	return a ^ b>>3
650}
651
652//go:noinline
653func bicshiftRL_ssa(a, b uint32) uint32 {
654	return a &^ (b >> 3)
655}
656
657//go:noinline
658func notshiftRL_ssa(a uint32) uint32 {
659	return ^(a >> 3)
660}
661
662//go:noinline
663func addshiftRA_ssa(a, b int32) int32 {
664	return a + b>>3
665}
666
667//go:noinline
668func subshiftRA_ssa(a, b int32) int32 {
669	return a - b>>3
670}
671
672//go:noinline
673func rsbshiftRA_ssa(a, b int32) int32 {
674	return a>>3 - b
675}
676
677//go:noinline
678func andshiftRA_ssa(a, b int32) int32 {
679	return a & (b >> 3)
680}
681
682//go:noinline
683func orshiftRA_ssa(a, b int32) int32 {
684	return a | b>>3
685}
686
687//go:noinline
688func xorshiftRA_ssa(a, b int32) int32 {
689	return a ^ b>>3
690}
691
692//go:noinline
693func bicshiftRA_ssa(a, b int32) int32 {
694	return a &^ (b >> 3)
695}
696
697//go:noinline
698func notshiftRA_ssa(a int32) int32 {
699	return ^(a >> 3)
700}
701
702//go:noinline
703func addshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
704	return a + b<<s
705}
706
707//go:noinline
708func subshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
709	return a - b<<s
710}
711
712//go:noinline
713func rsbshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
714	return a<<s - b
715}
716
717//go:noinline
718func andshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
719	return a & (b << s)
720}
721
722//go:noinline
723func orshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
724	return a | b<<s
725}
726
727//go:noinline
728func xorshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
729	return a ^ b<<s
730}
731
732//go:noinline
733func bicshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
734	return a &^ (b << s)
735}
736
737//go:noinline
738func notshiftLLreg_ssa(a uint32, s uint8) uint32 {
739	return ^(a << s)
740}
741
742//go:noinline
743func addshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
744	return a + b>>s
745}
746
747//go:noinline
748func subshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
749	return a - b>>s
750}
751
752//go:noinline
753func rsbshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
754	return a>>s - b
755}
756
757//go:noinline
758func andshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
759	return a & (b >> s)
760}
761
762//go:noinline
763func orshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
764	return a | b>>s
765}
766
767//go:noinline
768func xorshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
769	return a ^ b>>s
770}
771
772//go:noinline
773func bicshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
774	return a &^ (b >> s)
775}
776
777//go:noinline
778func notshiftRLreg_ssa(a uint32, s uint8) uint32 {
779	return ^(a >> s)
780}
781
782//go:noinline
783func addshiftRAreg_ssa(a, b int32, s uint8) int32 {
784	return a + b>>s
785}
786
787//go:noinline
788func subshiftRAreg_ssa(a, b int32, s uint8) int32 {
789	return a - b>>s
790}
791
792//go:noinline
793func rsbshiftRAreg_ssa(a, b int32, s uint8) int32 {
794	return a>>s - b
795}
796
797//go:noinline
798func andshiftRAreg_ssa(a, b int32, s uint8) int32 {
799	return a & (b >> s)
800}
801
802//go:noinline
803func orshiftRAreg_ssa(a, b int32, s uint8) int32 {
804	return a | b>>s
805}
806
807//go:noinline
808func xorshiftRAreg_ssa(a, b int32, s uint8) int32 {
809	return a ^ b>>s
810}
811
812//go:noinline
813func bicshiftRAreg_ssa(a, b int32, s uint8) int32 {
814	return a &^ (b >> s)
815}
816
817//go:noinline
818func notshiftRAreg_ssa(a int32, s uint8) int32 {
819	return ^(a >> s)
820}
821
822// test ARM shifted ops
823func testShiftedOps(t *testing.T) {
824	a, b := uint32(10), uint32(42)
825	if want, got := a+b<<3, addshiftLL_ssa(a, b); got != want {
826		t.Errorf("addshiftLL_ssa(10, 42) = %d want %d", got, want)
827	}
828	if want, got := a-b<<3, subshiftLL_ssa(a, b); got != want {
829		t.Errorf("subshiftLL_ssa(10, 42) = %d want %d", got, want)
830	}
831	if want, got := a<<3-b, rsbshiftLL_ssa(a, b); got != want {
832		t.Errorf("rsbshiftLL_ssa(10, 42) = %d want %d", got, want)
833	}
834	if want, got := a&(b<<3), andshiftLL_ssa(a, b); got != want {
835		t.Errorf("andshiftLL_ssa(10, 42) = %d want %d", got, want)
836	}
837	if want, got := a|b<<3, orshiftLL_ssa(a, b); got != want {
838		t.Errorf("orshiftLL_ssa(10, 42) = %d want %d", got, want)
839	}
840	if want, got := a^b<<3, xorshiftLL_ssa(a, b); got != want {
841		t.Errorf("xorshiftLL_ssa(10, 42) = %d want %d", got, want)
842	}
843	if want, got := a&^(b<<3), bicshiftLL_ssa(a, b); got != want {
844		t.Errorf("bicshiftLL_ssa(10, 42) = %d want %d", got, want)
845	}
846	if want, got := ^(a << 3), notshiftLL_ssa(a); got != want {
847		t.Errorf("notshiftLL_ssa(10) = %d want %d", got, want)
848	}
849	if want, got := a+b>>3, addshiftRL_ssa(a, b); got != want {
850		t.Errorf("addshiftRL_ssa(10, 42) = %d want %d", got, want)
851	}
852	if want, got := a-b>>3, subshiftRL_ssa(a, b); got != want {
853		t.Errorf("subshiftRL_ssa(10, 42) = %d want %d", got, want)
854	}
855	if want, got := a>>3-b, rsbshiftRL_ssa(a, b); got != want {
856		t.Errorf("rsbshiftRL_ssa(10, 42) = %d want %d", got, want)
857	}
858	if want, got := a&(b>>3), andshiftRL_ssa(a, b); got != want {
859		t.Errorf("andshiftRL_ssa(10, 42) = %d want %d", got, want)
860	}
861	if want, got := a|b>>3, orshiftRL_ssa(a, b); got != want {
862		t.Errorf("orshiftRL_ssa(10, 42) = %d want %d", got, want)
863	}
864	if want, got := a^b>>3, xorshiftRL_ssa(a, b); got != want {
865		t.Errorf("xorshiftRL_ssa(10, 42) = %d want %d", got, want)
866	}
867	if want, got := a&^(b>>3), bicshiftRL_ssa(a, b); got != want {
868		t.Errorf("bicshiftRL_ssa(10, 42) = %d want %d", got, want)
869	}
870	if want, got := ^(a >> 3), notshiftRL_ssa(a); got != want {
871		t.Errorf("notshiftRL_ssa(10) = %d want %d", got, want)
872	}
873	c, d := int32(10), int32(-42)
874	if want, got := c+d>>3, addshiftRA_ssa(c, d); got != want {
875		t.Errorf("addshiftRA_ssa(10, -42) = %d want %d", got, want)
876	}
877	if want, got := c-d>>3, subshiftRA_ssa(c, d); got != want {
878		t.Errorf("subshiftRA_ssa(10, -42) = %d want %d", got, want)
879	}
880	if want, got := c>>3-d, rsbshiftRA_ssa(c, d); got != want {
881		t.Errorf("rsbshiftRA_ssa(10, -42) = %d want %d", got, want)
882	}
883	if want, got := c&(d>>3), andshiftRA_ssa(c, d); got != want {
884		t.Errorf("andshiftRA_ssa(10, -42) = %d want %d", got, want)
885	}
886	if want, got := c|d>>3, orshiftRA_ssa(c, d); got != want {
887		t.Errorf("orshiftRA_ssa(10, -42) = %d want %d", got, want)
888	}
889	if want, got := c^d>>3, xorshiftRA_ssa(c, d); got != want {
890		t.Errorf("xorshiftRA_ssa(10, -42) = %d want %d", got, want)
891	}
892	if want, got := c&^(d>>3), bicshiftRA_ssa(c, d); got != want {
893		t.Errorf("bicshiftRA_ssa(10, -42) = %d want %d", got, want)
894	}
895	if want, got := ^(d >> 3), notshiftRA_ssa(d); got != want {
896		t.Errorf("notshiftRA_ssa(-42) = %d want %d", got, want)
897	}
898	s := uint8(3)
899	if want, got := a+b<<s, addshiftLLreg_ssa(a, b, s); got != want {
900		t.Errorf("addshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
901	}
902	if want, got := a-b<<s, subshiftLLreg_ssa(a, b, s); got != want {
903		t.Errorf("subshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
904	}
905	if want, got := a<<s-b, rsbshiftLLreg_ssa(a, b, s); got != want {
906		t.Errorf("rsbshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
907	}
908	if want, got := a&(b<<s), andshiftLLreg_ssa(a, b, s); got != want {
909		t.Errorf("andshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
910	}
911	if want, got := a|b<<s, orshiftLLreg_ssa(a, b, s); got != want {
912		t.Errorf("orshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
913	}
914	if want, got := a^b<<s, xorshiftLLreg_ssa(a, b, s); got != want {
915		t.Errorf("xorshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
916	}
917	if want, got := a&^(b<<s), bicshiftLLreg_ssa(a, b, s); got != want {
918		t.Errorf("bicshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
919	}
920	if want, got := ^(a << s), notshiftLLreg_ssa(a, s); got != want {
921		t.Errorf("notshiftLLreg_ssa(10) = %d want %d", got, want)
922	}
923	if want, got := a+b>>s, addshiftRLreg_ssa(a, b, s); got != want {
924		t.Errorf("addshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
925	}
926	if want, got := a-b>>s, subshiftRLreg_ssa(a, b, s); got != want {
927		t.Errorf("subshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
928	}
929	if want, got := a>>s-b, rsbshiftRLreg_ssa(a, b, s); got != want {
930		t.Errorf("rsbshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
931	}
932	if want, got := a&(b>>s), andshiftRLreg_ssa(a, b, s); got != want {
933		t.Errorf("andshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
934	}
935	if want, got := a|b>>s, orshiftRLreg_ssa(a, b, s); got != want {
936		t.Errorf("orshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
937	}
938	if want, got := a^b>>s, xorshiftRLreg_ssa(a, b, s); got != want {
939		t.Errorf("xorshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
940	}
941	if want, got := a&^(b>>s), bicshiftRLreg_ssa(a, b, s); got != want {
942		t.Errorf("bicshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
943	}
944	if want, got := ^(a >> s), notshiftRLreg_ssa(a, s); got != want {
945		t.Errorf("notshiftRLreg_ssa(10) = %d want %d", got, want)
946	}
947	if want, got := c+d>>s, addshiftRAreg_ssa(c, d, s); got != want {
948		t.Errorf("addshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
949	}
950	if want, got := c-d>>s, subshiftRAreg_ssa(c, d, s); got != want {
951		t.Errorf("subshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
952	}
953	if want, got := c>>s-d, rsbshiftRAreg_ssa(c, d, s); got != want {
954		t.Errorf("rsbshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
955	}
956	if want, got := c&(d>>s), andshiftRAreg_ssa(c, d, s); got != want {
957		t.Errorf("andshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
958	}
959	if want, got := c|d>>s, orshiftRAreg_ssa(c, d, s); got != want {
960		t.Errorf("orshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
961	}
962	if want, got := c^d>>s, xorshiftRAreg_ssa(c, d, s); got != want {
963		t.Errorf("xorshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
964	}
965	if want, got := c&^(d>>s), bicshiftRAreg_ssa(c, d, s); got != want {
966		t.Errorf("bicshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
967	}
968	if want, got := ^(d >> s), notshiftRAreg_ssa(d, s); got != want {
969		t.Errorf("notshiftRAreg_ssa(-42, 3) = %d want %d", got, want)
970	}
971}
972
973// TestArithmetic tests that both backends have the same result for arithmetic expressions.
974func TestArithmetic(t *testing.T) {
975	test64BitConstMult(t)
976	test64BitConstAdd(t)
977	testRegallocCVSpill(t)
978	testSubqToNegq(t)
979	testBitwiseLogic(t)
980	testOcom(t)
981	testLrot(t)
982	testShiftCX(t)
983	testSubConst(t)
984	testOverflowConstShift(t)
985	testArithRightShiftConstOverflow(t)
986	testRightShiftConstOverflow(t)
987	testArithConstShift(t)
988	testArithRshConst(t)
989	testLargeConst(t)
990	testLoadCombine(t)
991	testLoadSymCombine(t)
992	testShiftRemoval(t)
993	testShiftedOps(t)
994	testDivFixUp(t)
995	testDivisibleSignedPow2(t)
996	testDivisibility(t)
997}
998
999// testDivFixUp ensures that signed division fix-ups are being generated.
1000func testDivFixUp(t *testing.T) {
1001	defer func() {
1002		if r := recover(); r != nil {
1003			t.Error("testDivFixUp failed")
1004			if e, ok := r.(runtime.Error); ok {
1005				t.Logf("%v\n", e.Error())
1006			}
1007		}
1008	}()
1009	var w int8 = -128
1010	var x int16 = -32768
1011	var y int32 = -2147483648
1012	var z int64 = -9223372036854775808
1013
1014	for i := -5; i < 0; i++ {
1015		g8 = w / int8(i)
1016		g16 = x / int16(i)
1017		g32 = y / int32(i)
1018		g64 = z / int64(i)
1019		g8 = w % int8(i)
1020		g16 = x % int16(i)
1021		g32 = y % int32(i)
1022		g64 = z % int64(i)
1023	}
1024}
1025
1026//go:noinline
1027func divisible_int8_2to1(x int8) bool {
1028	return x%(1<<1) == 0
1029}
1030
1031//go:noinline
1032func divisible_int8_2to2(x int8) bool {
1033	return x%(1<<2) == 0
1034}
1035
1036//go:noinline
1037func divisible_int8_2to3(x int8) bool {
1038	return x%(1<<3) == 0
1039}
1040
1041//go:noinline
1042func divisible_int8_2to4(x int8) bool {
1043	return x%(1<<4) == 0
1044}
1045
1046//go:noinline
1047func divisible_int8_2to5(x int8) bool {
1048	return x%(1<<5) == 0
1049}
1050
1051//go:noinline
1052func divisible_int8_2to6(x int8) bool {
1053	return x%(1<<6) == 0
1054}
1055
1056//go:noinline
1057func divisible_int16_2to1(x int16) bool {
1058	return x%(1<<1) == 0
1059}
1060
1061//go:noinline
1062func divisible_int16_2to2(x int16) bool {
1063	return x%(1<<2) == 0
1064}
1065
1066//go:noinline
1067func divisible_int16_2to3(x int16) bool {
1068	return x%(1<<3) == 0
1069}
1070
1071//go:noinline
1072func divisible_int16_2to4(x int16) bool {
1073	return x%(1<<4) == 0
1074}
1075
1076//go:noinline
1077func divisible_int16_2to5(x int16) bool {
1078	return x%(1<<5) == 0
1079}
1080
1081//go:noinline
1082func divisible_int16_2to6(x int16) bool {
1083	return x%(1<<6) == 0
1084}
1085
1086//go:noinline
1087func divisible_int16_2to7(x int16) bool {
1088	return x%(1<<7) == 0
1089}
1090
1091//go:noinline
1092func divisible_int16_2to8(x int16) bool {
1093	return x%(1<<8) == 0
1094}
1095
1096//go:noinline
1097func divisible_int16_2to9(x int16) bool {
1098	return x%(1<<9) == 0
1099}
1100
1101//go:noinline
1102func divisible_int16_2to10(x int16) bool {
1103	return x%(1<<10) == 0
1104}
1105
1106//go:noinline
1107func divisible_int16_2to11(x int16) bool {
1108	return x%(1<<11) == 0
1109}
1110
1111//go:noinline
1112func divisible_int16_2to12(x int16) bool {
1113	return x%(1<<12) == 0
1114}
1115
1116//go:noinline
1117func divisible_int16_2to13(x int16) bool {
1118	return x%(1<<13) == 0
1119}
1120
1121//go:noinline
1122func divisible_int16_2to14(x int16) bool {
1123	return x%(1<<14) == 0
1124}
1125
1126//go:noinline
1127func divisible_int32_2to4(x int32) bool {
1128	return x%(1<<4) == 0
1129}
1130
1131//go:noinline
1132func divisible_int32_2to15(x int32) bool {
1133	return x%(1<<15) == 0
1134}
1135
1136//go:noinline
1137func divisible_int32_2to26(x int32) bool {
1138	return x%(1<<26) == 0
1139}
1140
1141//go:noinline
1142func divisible_int64_2to4(x int64) bool {
1143	return x%(1<<4) == 0
1144}
1145
1146//go:noinline
1147func divisible_int64_2to15(x int64) bool {
1148	return x%(1<<15) == 0
1149}
1150
1151//go:noinline
1152func divisible_int64_2to26(x int64) bool {
1153	return x%(1<<26) == 0
1154}
1155
1156//go:noinline
1157func divisible_int64_2to34(x int64) bool {
1158	return x%(1<<34) == 0
1159}
1160
1161//go:noinline
1162func divisible_int64_2to48(x int64) bool {
1163	return x%(1<<48) == 0
1164}
1165
1166//go:noinline
1167func divisible_int64_2to57(x int64) bool {
1168	return x%(1<<57) == 0
1169}
1170
1171// testDivisibleSignedPow2 confirms that x%(1<<k)==0 is rewritten correctly
1172func testDivisibleSignedPow2(t *testing.T) {
1173	var i int64
1174	var pow2 = []int64{
1175		1,
1176		1 << 1,
1177		1 << 2,
1178		1 << 3,
1179		1 << 4,
1180		1 << 5,
1181		1 << 6,
1182		1 << 7,
1183		1 << 8,
1184		1 << 9,
1185		1 << 10,
1186		1 << 11,
1187		1 << 12,
1188		1 << 13,
1189		1 << 14,
1190	}
1191	// exhaustive test for int8
1192	for i = math.MinInt8; i <= math.MaxInt8; i++ {
1193		if want, got := int8(i)%int8(pow2[1]) == 0, divisible_int8_2to1(int8(i)); got != want {
1194			t.Errorf("divisible_int8_2to1(%d) = %v want %v", i, got, want)
1195		}
1196		if want, got := int8(i)%int8(pow2[2]) == 0, divisible_int8_2to2(int8(i)); got != want {
1197			t.Errorf("divisible_int8_2to2(%d) = %v want %v", i, got, want)
1198		}
1199		if want, got := int8(i)%int8(pow2[3]) == 0, divisible_int8_2to3(int8(i)); got != want {
1200			t.Errorf("divisible_int8_2to3(%d) = %v want %v", i, got, want)
1201		}
1202		if want, got := int8(i)%int8(pow2[4]) == 0, divisible_int8_2to4(int8(i)); got != want {
1203			t.Errorf("divisible_int8_2to4(%d) = %v want %v", i, got, want)
1204		}
1205		if want, got := int8(i)%int8(pow2[5]) == 0, divisible_int8_2to5(int8(i)); got != want {
1206			t.Errorf("divisible_int8_2to5(%d) = %v want %v", i, got, want)
1207		}
1208		if want, got := int8(i)%int8(pow2[6]) == 0, divisible_int8_2to6(int8(i)); got != want {
1209			t.Errorf("divisible_int8_2to6(%d) = %v want %v", i, got, want)
1210		}
1211	}
1212	// exhaustive test for int16
1213	for i = math.MinInt16; i <= math.MaxInt16; i++ {
1214		if want, got := int16(i)%int16(pow2[1]) == 0, divisible_int16_2to1(int16(i)); got != want {
1215			t.Errorf("divisible_int16_2to1(%d) = %v want %v", i, got, want)
1216		}
1217		if want, got := int16(i)%int16(pow2[2]) == 0, divisible_int16_2to2(int16(i)); got != want {
1218			t.Errorf("divisible_int16_2to2(%d) = %v want %v", i, got, want)
1219		}
1220		if want, got := int16(i)%int16(pow2[3]) == 0, divisible_int16_2to3(int16(i)); got != want {
1221			t.Errorf("divisible_int16_2to3(%d) = %v want %v", i, got, want)
1222		}
1223		if want, got := int16(i)%int16(pow2[4]) == 0, divisible_int16_2to4(int16(i)); got != want {
1224			t.Errorf("divisible_int16_2to4(%d) = %v want %v", i, got, want)
1225		}
1226		if want, got := int16(i)%int16(pow2[5]) == 0, divisible_int16_2to5(int16(i)); got != want {
1227			t.Errorf("divisible_int16_2to5(%d) = %v want %v", i, got, want)
1228		}
1229		if want, got := int16(i)%int16(pow2[6]) == 0, divisible_int16_2to6(int16(i)); got != want {
1230			t.Errorf("divisible_int16_2to6(%d) = %v want %v", i, got, want)
1231		}
1232		if want, got := int16(i)%int16(pow2[7]) == 0, divisible_int16_2to7(int16(i)); got != want {
1233			t.Errorf("divisible_int16_2to7(%d) = %v want %v", i, got, want)
1234		}
1235		if want, got := int16(i)%int16(pow2[8]) == 0, divisible_int16_2to8(int16(i)); got != want {
1236			t.Errorf("divisible_int16_2to8(%d) = %v want %v", i, got, want)
1237		}
1238		if want, got := int16(i)%int16(pow2[9]) == 0, divisible_int16_2to9(int16(i)); got != want {
1239			t.Errorf("divisible_int16_2to9(%d) = %v want %v", i, got, want)
1240		}
1241		if want, got := int16(i)%int16(pow2[10]) == 0, divisible_int16_2to10(int16(i)); got != want {
1242			t.Errorf("divisible_int16_2to10(%d) = %v want %v", i, got, want)
1243		}
1244		if want, got := int16(i)%int16(pow2[11]) == 0, divisible_int16_2to11(int16(i)); got != want {
1245			t.Errorf("divisible_int16_2to11(%d) = %v want %v", i, got, want)
1246		}
1247		if want, got := int16(i)%int16(pow2[12]) == 0, divisible_int16_2to12(int16(i)); got != want {
1248			t.Errorf("divisible_int16_2to12(%d) = %v want %v", i, got, want)
1249		}
1250		if want, got := int16(i)%int16(pow2[13]) == 0, divisible_int16_2to13(int16(i)); got != want {
1251			t.Errorf("divisible_int16_2to13(%d) = %v want %v", i, got, want)
1252		}
1253		if want, got := int16(i)%int16(pow2[14]) == 0, divisible_int16_2to14(int16(i)); got != want {
1254			t.Errorf("divisible_int16_2to14(%d) = %v want %v", i, got, want)
1255		}
1256	}
1257	// spot check for int32 and int64
1258	var (
1259		two4  int64 = 1 << 4
1260		two15 int64 = 1 << 15
1261		two26 int64 = 1 << 26
1262		two34 int64 = 1 << 34
1263		two48 int64 = 1 << 48
1264		two57 int64 = 1 << 57
1265	)
1266	var xs = []int64{two4, two4 + 3, -3 * two4, -3*two4 + 1,
1267		two15, two15 + 3, -3 * two15, -3*two15 + 1,
1268		two26, two26 + 37, -5 * two26, -5*two26 + 2,
1269		two34, two34 + 356, -7 * two34, -7*two34 + 13,
1270		two48, two48 + 3000, -12 * two48, -12*two48 + 1111,
1271		two57, two57 + 397654, -15 * two57, -15*two57 + 11234,
1272	}
1273	for _, x := range xs {
1274		if int64(int32(x)) == x {
1275			if want, got := int32(x)%int32(two4) == 0, divisible_int32_2to4(int32(x)); got != want {
1276				t.Errorf("divisible_int32_2to4(%d) = %v want %v", x, got, want)
1277			}
1278
1279			if want, got := int32(x)%int32(two15) == 0, divisible_int32_2to15(int32(x)); got != want {
1280				t.Errorf("divisible_int32_2to15(%d) = %v want %v", x, got, want)
1281			}
1282
1283			if want, got := int32(x)%int32(two26) == 0, divisible_int32_2to26(int32(x)); got != want {
1284				t.Errorf("divisible_int32_2to26(%d) = %v want %v", x, got, want)
1285			}
1286		}
1287		// spot check for int64
1288		if want, got := x%two4 == 0, divisible_int64_2to4(x); got != want {
1289			t.Errorf("divisible_int64_2to4(%d) = %v want %v", x, got, want)
1290		}
1291
1292		if want, got := x%two15 == 0, divisible_int64_2to15(x); got != want {
1293			t.Errorf("divisible_int64_2to15(%d) = %v want %v", x, got, want)
1294		}
1295
1296		if want, got := x%two26 == 0, divisible_int64_2to26(x); got != want {
1297			t.Errorf("divisible_int64_2to26(%d) = %v want %v", x, got, want)
1298		}
1299
1300		if want, got := x%two34 == 0, divisible_int64_2to34(x); got != want {
1301			t.Errorf("divisible_int64_2to34(%d) = %v want %v", x, got, want)
1302		}
1303
1304		if want, got := x%two48 == 0, divisible_int64_2to48(x); got != want {
1305			t.Errorf("divisible_int64_2to48(%d) = %v want %v", x, got, want)
1306		}
1307
1308		if want, got := x%two57 == 0, divisible_int64_2to57(x); got != want {
1309			t.Errorf("divisible_int64_2to57(%d) = %v want %v", x, got, want)
1310		}
1311	}
1312}
1313
1314func div6_uint8(n uint8) bool {
1315	return n%6 == 0
1316}
1317
1318//go:noinline
1319func div6_uint16(n uint16) bool {
1320	return n%6 == 0
1321}
1322
1323//go:noinline
1324func div6_uint32(n uint32) bool {
1325	return n%6 == 0
1326}
1327
1328//go:noinline
1329func div6_uint64(n uint64) bool {
1330	return n%6 == 0
1331}
1332
1333//go:noinline
1334func div19_uint8(n uint8) bool {
1335	return n%19 == 0
1336}
1337
1338//go:noinline
1339func div19_uint16(n uint16) bool {
1340	return n%19 == 0
1341}
1342
1343//go:noinline
1344func div19_uint32(n uint32) bool {
1345	return n%19 == 0
1346}
1347
1348//go:noinline
1349func div19_uint64(n uint64) bool {
1350	return n%19 == 0
1351}
1352
1353//go:noinline
1354func div6_int8(n int8) bool {
1355	return n%6 == 0
1356}
1357
1358//go:noinline
1359func div6_int16(n int16) bool {
1360	return n%6 == 0
1361}
1362
1363//go:noinline
1364func div6_int32(n int32) bool {
1365	return n%6 == 0
1366}
1367
1368//go:noinline
1369func div6_int64(n int64) bool {
1370	return n%6 == 0
1371}
1372
1373//go:noinline
1374func div19_int8(n int8) bool {
1375	return n%19 == 0
1376}
1377
1378//go:noinline
1379func div19_int16(n int16) bool {
1380	return n%19 == 0
1381}
1382
1383//go:noinline
1384func div19_int32(n int32) bool {
1385	return n%19 == 0
1386}
1387
1388//go:noinline
1389func div19_int64(n int64) bool {
1390	return n%19 == 0
1391}
1392
1393// testDivisibility confirms that rewrite rules x%c ==0 for c constant are correct.
1394func testDivisibility(t *testing.T) {
1395	// unsigned tests
1396	// test an even and an odd divisor
1397	var sixU, nineteenU uint64 = 6, 19
1398	// test all inputs for uint8, uint16
1399	for i := uint64(0); i <= math.MaxUint16; i++ {
1400		if i <= math.MaxUint8 {
1401			if want, got := uint8(i)%uint8(sixU) == 0, div6_uint8(uint8(i)); got != want {
1402				t.Errorf("div6_uint8(%d) = %v want %v", i, got, want)
1403			}
1404			if want, got := uint8(i)%uint8(nineteenU) == 0, div19_uint8(uint8(i)); got != want {
1405				t.Errorf("div6_uint19(%d) = %v want %v", i, got, want)
1406			}
1407		}
1408		if want, got := uint16(i)%uint16(sixU) == 0, div6_uint16(uint16(i)); got != want {
1409			t.Errorf("div6_uint16(%d) = %v want %v", i, got, want)
1410		}
1411		if want, got := uint16(i)%uint16(nineteenU) == 0, div19_uint16(uint16(i)); got != want {
1412			t.Errorf("div19_uint16(%d) = %v want %v", i, got, want)
1413		}
1414	}
1415	var maxU32, maxU64 uint64 = math.MaxUint32, math.MaxUint64
1416	// spot check inputs for uint32 and uint64
1417	xu := []uint64{
1418		0, 1, 2, 3, 4, 5,
1419		sixU, 2 * sixU, 3 * sixU, 5 * sixU, 12345 * sixU,
1420		sixU + 1, 2*sixU - 5, 3*sixU + 3, 5*sixU + 4, 12345*sixU - 2,
1421		nineteenU, 2 * nineteenU, 3 * nineteenU, 5 * nineteenU, 12345 * nineteenU,
1422		nineteenU + 1, 2*nineteenU - 5, 3*nineteenU + 3, 5*nineteenU + 4, 12345*nineteenU - 2,
1423		maxU32, maxU32 - 1, maxU32 - 2, maxU32 - 3, maxU32 - 4,
1424		maxU32 - 5, maxU32 - 6, maxU32 - 7, maxU32 - 8,
1425		maxU32 - 9, maxU32 - 10, maxU32 - 11, maxU32 - 12,
1426		maxU32 - 13, maxU32 - 14, maxU32 - 15, maxU32 - 16,
1427		maxU32 - 17, maxU32 - 18, maxU32 - 19, maxU32 - 20,
1428		maxU64, maxU64 - 1, maxU64 - 2, maxU64 - 3, maxU64 - 4,
1429		maxU64 - 5, maxU64 - 6, maxU64 - 7, maxU64 - 8,
1430		maxU64 - 9, maxU64 - 10, maxU64 - 11, maxU64 - 12,
1431		maxU64 - 13, maxU64 - 14, maxU64 - 15, maxU64 - 16,
1432		maxU64 - 17, maxU64 - 18, maxU64 - 19, maxU64 - 20,
1433	}
1434	for _, x := range xu {
1435		if x <= maxU32 {
1436			if want, got := uint32(x)%uint32(sixU) == 0, div6_uint32(uint32(x)); got != want {
1437				t.Errorf("div6_uint32(%d) = %v want %v", x, got, want)
1438			}
1439			if want, got := uint32(x)%uint32(nineteenU) == 0, div19_uint32(uint32(x)); got != want {
1440				t.Errorf("div19_uint32(%d) = %v want %v", x, got, want)
1441			}
1442		}
1443		if want, got := x%sixU == 0, div6_uint64(x); got != want {
1444			t.Errorf("div6_uint64(%d) = %v want %v", x, got, want)
1445		}
1446		if want, got := x%nineteenU == 0, div19_uint64(x); got != want {
1447			t.Errorf("div19_uint64(%d) = %v want %v", x, got, want)
1448		}
1449	}
1450
1451	// signed tests
1452	// test an even and an odd divisor
1453	var sixS, nineteenS int64 = 6, 19
1454	// test all inputs for int8, int16
1455	for i := int64(math.MinInt16); i <= math.MaxInt16; i++ {
1456		if math.MinInt8 <= i && i <= math.MaxInt8 {
1457			if want, got := int8(i)%int8(sixS) == 0, div6_int8(int8(i)); got != want {
1458				t.Errorf("div6_int8(%d) = %v want %v", i, got, want)
1459			}
1460			if want, got := int8(i)%int8(nineteenS) == 0, div19_int8(int8(i)); got != want {
1461				t.Errorf("div6_int19(%d) = %v want %v", i, got, want)
1462			}
1463		}
1464		if want, got := int16(i)%int16(sixS) == 0, div6_int16(int16(i)); got != want {
1465			t.Errorf("div6_int16(%d) = %v want %v", i, got, want)
1466		}
1467		if want, got := int16(i)%int16(nineteenS) == 0, div19_int16(int16(i)); got != want {
1468			t.Errorf("div19_int16(%d) = %v want %v", i, got, want)
1469		}
1470	}
1471	var minI32, maxI32, minI64, maxI64 int64 = math.MinInt32, math.MaxInt32, math.MinInt64, math.MaxInt64
1472	// spot check inputs for int32 and int64
1473	xs := []int64{
1474		0, 1, 2, 3, 4, 5,
1475		-1, -2, -3, -4, -5,
1476		sixS, 2 * sixS, 3 * sixS, 5 * sixS, 12345 * sixS,
1477		sixS + 1, 2*sixS - 5, 3*sixS + 3, 5*sixS + 4, 12345*sixS - 2,
1478		-sixS, -2 * sixS, -3 * sixS, -5 * sixS, -12345 * sixS,
1479		-sixS + 1, -2*sixS - 5, -3*sixS + 3, -5*sixS + 4, -12345*sixS - 2,
1480		nineteenS, 2 * nineteenS, 3 * nineteenS, 5 * nineteenS, 12345 * nineteenS,
1481		nineteenS + 1, 2*nineteenS - 5, 3*nineteenS + 3, 5*nineteenS + 4, 12345*nineteenS - 2,
1482		-nineteenS, -2 * nineteenS, -3 * nineteenS, -5 * nineteenS, -12345 * nineteenS,
1483		-nineteenS + 1, -2*nineteenS - 5, -3*nineteenS + 3, -5*nineteenS + 4, -12345*nineteenS - 2,
1484		minI32, minI32 + 1, minI32 + 2, minI32 + 3, minI32 + 4,
1485		minI32 + 5, minI32 + 6, minI32 + 7, minI32 + 8,
1486		minI32 + 9, minI32 + 10, minI32 + 11, minI32 + 12,
1487		minI32 + 13, minI32 + 14, minI32 + 15, minI32 + 16,
1488		minI32 + 17, minI32 + 18, minI32 + 19, minI32 + 20,
1489		maxI32, maxI32 - 1, maxI32 - 2, maxI32 - 3, maxI32 - 4,
1490		maxI32 - 5, maxI32 - 6, maxI32 - 7, maxI32 - 8,
1491		maxI32 - 9, maxI32 - 10, maxI32 - 11, maxI32 - 12,
1492		maxI32 - 13, maxI32 - 14, maxI32 - 15, maxI32 - 16,
1493		maxI32 - 17, maxI32 - 18, maxI32 - 19, maxI32 - 20,
1494		minI64, minI64 + 1, minI64 + 2, minI64 + 3, minI64 + 4,
1495		minI64 + 5, minI64 + 6, minI64 + 7, minI64 + 8,
1496		minI64 + 9, minI64 + 10, minI64 + 11, minI64 + 12,
1497		minI64 + 13, minI64 + 14, minI64 + 15, minI64 + 16,
1498		minI64 + 17, minI64 + 18, minI64 + 19, minI64 + 20,
1499		maxI64, maxI64 - 1, maxI64 - 2, maxI64 - 3, maxI64 - 4,
1500		maxI64 - 5, maxI64 - 6, maxI64 - 7, maxI64 - 8,
1501		maxI64 - 9, maxI64 - 10, maxI64 - 11, maxI64 - 12,
1502		maxI64 - 13, maxI64 - 14, maxI64 - 15, maxI64 - 16,
1503		maxI64 - 17, maxI64 - 18, maxI64 - 19, maxI64 - 20,
1504	}
1505	for _, x := range xs {
1506		if minI32 <= x && x <= maxI32 {
1507			if want, got := int32(x)%int32(sixS) == 0, div6_int32(int32(x)); got != want {
1508				t.Errorf("div6_int32(%d) = %v want %v", x, got, want)
1509			}
1510			if want, got := int32(x)%int32(nineteenS) == 0, div19_int32(int32(x)); got != want {
1511				t.Errorf("div19_int32(%d) = %v want %v", x, got, want)
1512			}
1513		}
1514		if want, got := x%sixS == 0, div6_int64(x); got != want {
1515			t.Errorf("div6_int64(%d) = %v want %v", x, got, want)
1516		}
1517		if want, got := x%nineteenS == 0, div19_int64(x); got != want {
1518			t.Errorf("div19_int64(%d) = %v want %v", x, got, want)
1519		}
1520	}
1521}
1522
1523//go:noinline
1524func genREV16_1(c uint64) uint64 {
1525	b := ((c & 0xff00ff00ff00ff00) >> 8) | ((c & 0x00ff00ff00ff00ff) << 8)
1526	return b
1527}
1528
1529//go:noinline
1530func genREV16_2(c uint64) uint64 {
1531	b := ((c & 0xff00ff00) >> 8) | ((c & 0x00ff00ff) << 8)
1532	return b
1533}
1534
1535//go:noinline
1536func genREV16W(c uint32) uint32 {
1537	b := ((c & 0xff00ff00) >> 8) | ((c & 0x00ff00ff) << 8)
1538	return b
1539}
1540
1541func TestREV16(t *testing.T) {
1542	x := uint64(0x8f7f6f5f4f3f2f1f)
1543	want1 := uint64(0x7f8f5f6f3f4f1f2f)
1544	want2 := uint64(0x3f4f1f2f)
1545
1546	got1 := genREV16_1(x)
1547	if got1 != want1 {
1548		t.Errorf("genREV16_1(%#x) = %#x want %#x", x, got1, want1)
1549	}
1550	got2 := genREV16_2(x)
1551	if got2 != want2 {
1552		t.Errorf("genREV16_2(%#x) = %#x want %#x", x, got2, want2)
1553	}
1554}
1555
1556func TestREV16W(t *testing.T) {
1557	x := uint32(0x4f3f2f1f)
1558	want := uint32(0x3f4f1f2f)
1559
1560	got := genREV16W(x)
1561	if got != want {
1562		t.Errorf("genREV16W(%#x) = %#x want %#x", x, got, want)
1563	}
1564}
1565