]> Cypherpunks.ru repositories - gostls13.git/blob - test/codegen/arithmetic.go
0d6d9690000ebe05f6ba53a00e676ce41126d812
[gostls13.git] / test / codegen / arithmetic.go
1 // asmcheck
2
3 // Copyright 2018 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 package codegen
8
9 // This file contains codegen tests related to arithmetic
10 // simplifications and optimizations on integer types.
11 // For codegen tests on float types, see floats.go.
12
13 // ----------------- //
14 //    Addition       //
15 // ----------------- //
16
17 func AddLargeConst(a uint64, out []uint64) {
18         // ppc64x/power10:"ADD\t[$]4294967296,"
19         // ppc64x/power9:"MOVD\t[$]i64.0000000100000000[(]SB[)]", "ADD\tR[0-9]*"
20         // ppc64x/power8:"MOVD\t[$]i64.0000000100000000[(]SB[)]", "ADD\tR[0-9]*"
21         out[0] = a + 0x100000000
22         // ppc64x/power10:"ADD\t[$]-8589934592,"
23         // ppc64x/power9:"MOVD\t[$]i64.fffffffe00000000[(]SB[)]", "ADD\tR[0-9]*"
24         // ppc64x/power8:"MOVD\t[$]i64.fffffffe00000000[(]SB[)]", "ADD\tR[0-9]*"
25         out[1] = a + 0xFFFFFFFE00000000
26 }
27
28 // ----------------- //
29 //    Subtraction    //
30 // ----------------- //
31
32 var ef int
33
34 func SubMem(arr []int, b, c, d int) int {
35         // 386:`SUBL\s[A-Z]+,\s8\([A-Z]+\)`
36         // amd64:`SUBQ\s[A-Z]+,\s16\([A-Z]+\)`
37         arr[2] -= b
38         // 386:`SUBL\s[A-Z]+,\s12\([A-Z]+\)`
39         // amd64:`SUBQ\s[A-Z]+,\s24\([A-Z]+\)`
40         arr[3] -= b
41         // 386:`DECL\s16\([A-Z]+\)`
42         arr[4]--
43         // 386:`ADDL\s[$]-20,\s20\([A-Z]+\)`
44         arr[5] -= 20
45         // 386:`SUBL\s\([A-Z]+\)\([A-Z]+\*4\),\s[A-Z]+`
46         ef -= arr[b]
47         // 386:`SUBL\s[A-Z]+,\s\([A-Z]+\)\([A-Z]+\*4\)`
48         arr[c] -= b
49         // 386:`ADDL\s[$]-15,\s\([A-Z]+\)\([A-Z]+\*4\)`
50         arr[d] -= 15
51         // 386:`DECL\s\([A-Z]+\)\([A-Z]+\*4\)`
52         arr[b]--
53         // amd64:`DECQ\s64\([A-Z]+\)`
54         arr[8]--
55         // 386:"SUBL\t4"
56         // amd64:"SUBQ\t8"
57         return arr[0] - arr[1]
58 }
59
60 func SubFromConst(a int) int {
61         // ppc64x: `SUBC\tR[0-9]+,\s[$]40,\sR`
62         b := 40 - a
63         return b
64 }
65
66 func SubFromConstNeg(a int) int {
67         // ppc64x: `ADD\t[$]40,\sR[0-9]+,\sR`
68         c := 40 - (-a)
69         return c
70 }
71
72 func SubSubFromConst(a int) int {
73         // ppc64x: `ADD\t[$]20,\sR[0-9]+,\sR`
74         c := 40 - (20 - a)
75         return c
76 }
77
78 func AddSubFromConst(a int) int {
79         // ppc64x: `SUBC\tR[0-9]+,\s[$]60,\sR`
80         c := 40 + (20 - a)
81         return c
82 }
83
84 func NegSubFromConst(a int) int {
85         // ppc64x: `ADD\t[$]-20,\sR[0-9]+,\sR`
86         c := -(20 - a)
87         return c
88 }
89
90 func NegAddFromConstNeg(a int) int {
91         // ppc64x: `SUBC\tR[0-9]+,\s[$]40,\sR`
92         c := -(-40 + a)
93         return c
94 }
95
96 func SubSubNegSimplify(a, b int) int {
97         // amd64:"NEGQ"
98         // ppc64x:"NEG"
99         r := (a - b) - a
100         return r
101 }
102
103 func SubAddSimplify(a, b int) int {
104         // amd64:-"SUBQ",-"ADDQ"
105         // ppc64x:-"SUB",-"ADD"
106         r := a + (b - a)
107         return r
108 }
109
110 func SubAddSimplify2(a, b, c int) (int, int, int, int, int, int) {
111         // amd64:-"ADDQ"
112         r := (a + b) - (a + c)
113         // amd64:-"ADDQ"
114         r1 := (a + b) - (c + a)
115         // amd64:-"ADDQ"
116         r2 := (b + a) - (a + c)
117         // amd64:-"ADDQ"
118         r3 := (b + a) - (c + a)
119         // amd64:-"SUBQ"
120         r4 := (a - c) + (c + b)
121         // amd64:-"SUBQ"
122         r5 := (a - c) + (b + c)
123         return r, r1, r2, r3, r4, r5
124 }
125
126 func SubAddNegSimplify(a, b int) int {
127         // amd64:"NEGQ",-"ADDQ",-"SUBQ"
128         // ppc64x:"NEG",-"ADD",-"SUB"
129         r := a - (b + a)
130         return r
131 }
132
133 func AddAddSubSimplify(a, b, c int) int {
134         // amd64:-"SUBQ"
135         // ppc64x:-"SUB"
136         r := a + (b + (c - a))
137         return r
138 }
139
140 // -------------------- //
141 //    Multiplication    //
142 // -------------------- //
143
144 func Pow2Muls(n1, n2 int) (int, int) {
145         // amd64:"SHLQ\t[$]5",-"IMULQ"
146         // 386:"SHLL\t[$]5",-"IMULL"
147         // arm:"SLL\t[$]5",-"MUL"
148         // arm64:"LSL\t[$]5",-"MUL"
149         // ppc64x:"SLD\t[$]5",-"MUL"
150         a := n1 * 32
151
152         // amd64:"SHLQ\t[$]6",-"IMULQ"
153         // 386:"SHLL\t[$]6",-"IMULL"
154         // arm:"SLL\t[$]6",-"MUL"
155         // arm64:`NEG\sR[0-9]+<<6,\sR[0-9]+`,-`LSL`,-`MUL`
156         // ppc64x:"SLD\t[$]6","NEG\\sR[0-9]+,\\sR[0-9]+",-"MUL"
157         b := -64 * n2
158
159         return a, b
160 }
161
162 func Mul_96(n int) int {
163         // amd64:`SHLQ\t[$]5`,`LEAQ\t\(.*\)\(.*\*2\),`,-`IMULQ`
164         // 386:`SHLL\t[$]5`,`LEAL\t\(.*\)\(.*\*2\),`,-`IMULL`
165         // arm64:`LSL\t[$]5`,`ADD\sR[0-9]+<<1,\sR[0-9]+`,-`MUL`
166         // arm:`SLL\t[$]5`,`ADD\sR[0-9]+<<1,\sR[0-9]+`,-`MUL`
167         // s390x:`SLD\t[$]5`,`SLD\t[$]6`,-`MULLD`
168         return n * 96
169 }
170
171 func Mul_n120(n int) int {
172         // s390x:`SLD\t[$]3`,`SLD\t[$]7`,-`MULLD`
173         return n * -120
174 }
175
176 func MulMemSrc(a []uint32, b []float32) {
177         // 386:`IMULL\s4\([A-Z]+\),\s[A-Z]+`
178         a[0] *= a[1]
179         // 386/sse2:`MULSS\s4\([A-Z]+\),\sX[0-9]+`
180         // amd64:`MULSS\s4\([A-Z]+\),\sX[0-9]+`
181         b[0] *= b[1]
182 }
183
184 // Multiplications merging tests
185
186 func MergeMuls1(n int) int {
187         // amd64:"IMUL3Q\t[$]46"
188         // 386:"IMUL3L\t[$]46"
189         // ppc64x:"MULLD\t[$]46"
190         return 15*n + 31*n // 46n
191 }
192
193 func MergeMuls2(n int) int {
194         // amd64:"IMUL3Q\t[$]23","(ADDQ\t[$]29)|(LEAQ\t29)"
195         // 386:"IMUL3L\t[$]23","ADDL\t[$]29"
196         // ppc64x/power9:"MADDLD",-"MULLD\t[$]23",-"ADD\t[$]29"
197         // ppc64x/power8:"MULLD\t[$]23","ADD\t[$]29"
198         return 5*n + 7*(n+1) + 11*(n+2) // 23n + 29
199 }
200
201 func MergeMuls3(a, n int) int {
202         // amd64:"ADDQ\t[$]19",-"IMULQ\t[$]19"
203         // 386:"ADDL\t[$]19",-"IMULL\t[$]19"
204         // ppc64x:"ADD\t[$]19",-"MULLD\t[$]19"
205         return a*n + 19*n // (a+19)n
206 }
207
208 func MergeMuls4(n int) int {
209         // amd64:"IMUL3Q\t[$]14"
210         // 386:"IMUL3L\t[$]14"
211         // ppc64x:"MULLD\t[$]14"
212         return 23*n - 9*n // 14n
213 }
214
215 func MergeMuls5(a, n int) int {
216         // amd64:"ADDQ\t[$]-19",-"IMULQ\t[$]19"
217         // 386:"ADDL\t[$]-19",-"IMULL\t[$]19"
218         // ppc64x:"ADD\t[$]-19",-"MULLD\t[$]19"
219         return a*n - 19*n // (a-19)n
220 }
221
222 // -------------- //
223 //    Division    //
224 // -------------- //
225
226 func DivMemSrc(a []float64) {
227         // 386/sse2:`DIVSD\s8\([A-Z]+\),\sX[0-9]+`
228         // amd64:`DIVSD\s8\([A-Z]+\),\sX[0-9]+`
229         a[0] /= a[1]
230 }
231
232 func Pow2Divs(n1 uint, n2 int) (uint, int) {
233         // 386:"SHRL\t[$]5",-"DIVL"
234         // amd64:"SHRQ\t[$]5",-"DIVQ"
235         // arm:"SRL\t[$]5",-".*udiv"
236         // arm64:"LSR\t[$]5",-"UDIV"
237         // ppc64x:"SRD"
238         a := n1 / 32 // unsigned
239
240         // amd64:"SARQ\t[$]6",-"IDIVQ"
241         // 386:"SARL\t[$]6",-"IDIVL"
242         // arm:"SRA\t[$]6",-".*udiv"
243         // arm64:"ASR\t[$]6",-"SDIV"
244         // ppc64x:"SRAD"
245         b := n2 / 64 // signed
246
247         return a, b
248 }
249
250 // Check that constant divisions get turned into MULs
251 func ConstDivs(n1 uint, n2 int) (uint, int) {
252         // amd64:"MOVQ\t[$]-1085102592571150095","MULQ",-"DIVQ"
253         // 386:"MOVL\t[$]-252645135","MULL",-"DIVL"
254         // arm64:`MOVD`,`UMULH`,-`DIV`
255         // arm:`MOVW`,`MUL`,-`.*udiv`
256         a := n1 / 17 // unsigned
257
258         // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ"
259         // 386:"MOVL\t[$]-252645135","IMULL",-"IDIVL"
260         // arm64:`SMULH`,-`DIV`
261         // arm:`MOVW`,`MUL`,-`.*udiv`
262         b := n2 / 17 // signed
263
264         return a, b
265 }
266
267 func FloatDivs(a []float32) float32 {
268         // amd64:`DIVSS\s8\([A-Z]+\),\sX[0-9]+`
269         // 386/sse2:`DIVSS\s8\([A-Z]+\),\sX[0-9]+`
270         return a[1] / a[2]
271 }
272
273 func Pow2Mods(n1 uint, n2 int) (uint, int) {
274         // 386:"ANDL\t[$]31",-"DIVL"
275         // amd64:"ANDL\t[$]31",-"DIVQ"
276         // arm:"AND\t[$]31",-".*udiv"
277         // arm64:"AND\t[$]31",-"UDIV"
278         // ppc64x:"RLDICL"
279         a := n1 % 32 // unsigned
280
281         // 386:"SHRL",-"IDIVL"
282         // amd64:"SHRQ",-"IDIVQ"
283         // arm:"SRA",-".*udiv"
284         // arm64:"ASR",-"REM"
285         // ppc64x:"SRAD"
286         b := n2 % 64 // signed
287
288         return a, b
289 }
290
291 // Check that signed divisibility checks get converted to AND on low bits
292 func Pow2DivisibleSigned(n1, n2 int) (bool, bool) {
293         // 386:"TESTL\t[$]63",-"DIVL",-"SHRL"
294         // amd64:"TESTQ\t[$]63",-"DIVQ",-"SHRQ"
295         // arm:"AND\t[$]63",-".*udiv",-"SRA"
296         // arm64:"TST\t[$]63",-"UDIV",-"ASR",-"AND"
297         // ppc64x:"RLDICL",-"SRAD"
298         a := n1%64 == 0 // signed divisible
299
300         // 386:"TESTL\t[$]63",-"DIVL",-"SHRL"
301         // amd64:"TESTQ\t[$]63",-"DIVQ",-"SHRQ"
302         // arm:"AND\t[$]63",-".*udiv",-"SRA"
303         // arm64:"TST\t[$]63",-"UDIV",-"ASR",-"AND"
304         // ppc64x:"RLDICL",-"SRAD"
305         b := n2%64 != 0 // signed indivisible
306
307         return a, b
308 }
309
310 // Check that constant modulo divs get turned into MULs
311 func ConstMods(n1 uint, n2 int) (uint, int) {
312         // amd64:"MOVQ\t[$]-1085102592571150095","MULQ",-"DIVQ"
313         // 386:"MOVL\t[$]-252645135","MULL",-"DIVL"
314         // arm64:`MOVD`,`UMULH`,-`DIV`
315         // arm:`MOVW`,`MUL`,-`.*udiv`
316         a := n1 % 17 // unsigned
317
318         // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ"
319         // 386:"MOVL\t[$]-252645135","IMULL",-"IDIVL"
320         // arm64:`SMULH`,-`DIV`
321         // arm:`MOVW`,`MUL`,-`.*udiv`
322         b := n2 % 17 // signed
323
324         return a, b
325 }
326
327 // Check that divisibility checks x%c==0 are converted to MULs and rotates
328 func DivisibleU(n uint) (bool, bool) {
329         // amd64:"MOVQ\t[$]-6148914691236517205","IMULQ","ROLQ\t[$]63",-"DIVQ"
330         // 386:"IMUL3L\t[$]-1431655765","ROLL\t[$]31",-"DIVQ"
331         // arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ROR",-"DIV"
332         // arm:"MUL","CMP\t[$]715827882",-".*udiv"
333         // ppc64x:"MULLD","ROTL\t[$]63"
334         even := n%6 == 0
335
336         // amd64:"MOVQ\t[$]-8737931403336103397","IMULQ",-"ROLQ",-"DIVQ"
337         // 386:"IMUL3L\t[$]678152731",-"ROLL",-"DIVQ"
338         // arm64:"MOVD\t[$]-8737931403336103397","MUL",-"ROR",-"DIV"
339         // arm:"MUL","CMP\t[$]226050910",-".*udiv"
340         // ppc64x:"MULLD",-"ROTL"
341         odd := n%19 == 0
342
343         return even, odd
344 }
345
346 func Divisible(n int) (bool, bool) {
347         // amd64:"IMULQ","ADD","ROLQ\t[$]63",-"DIVQ"
348         // 386:"IMUL3L\t[$]-1431655765","ADDL\t[$]715827882","ROLL\t[$]31",-"DIVQ"
349         // arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ADD\tR","ROR",-"DIV"
350         // arm:"MUL","ADD\t[$]715827882",-".*udiv"
351         // ppc64x/power8:"MULLD","ADD","ROTL\t[$]63"
352         // ppc64x/power9:"MADDLD","ROTL\t[$]63"
353         even := n%6 == 0
354
355         // amd64:"IMULQ","ADD",-"ROLQ",-"DIVQ"
356         // 386:"IMUL3L\t[$]678152731","ADDL\t[$]113025455",-"ROLL",-"DIVQ"
357         // arm64:"MUL","MOVD\t[$]485440633518672410","ADD",-"ROR",-"DIV"
358         // arm:"MUL","ADD\t[$]113025455",-".*udiv"
359         // ppc64x/power8:"MULLD","ADD",-"ROTL"
360         // ppc64x/power9:"MADDLD",-"ROTL"
361         odd := n%19 == 0
362
363         return even, odd
364 }
365
366 // Check that fix-up code is not generated for divisions where it has been proven that
367 // that the divisor is not -1 or that the dividend is > MinIntNN.
368 func NoFix64A(divr int64) (int64, int64) {
369         var d int64 = 42
370         var e int64 = 84
371         if divr > 5 {
372                 d /= divr // amd64:-"JMP"
373                 e %= divr // amd64:-"JMP"
374                 // The following statement is to avoid conflict between the above check
375                 // and the normal JMP generated at the end of the block.
376                 d += e
377         }
378         return d, e
379 }
380
381 func NoFix64B(divd int64) (int64, int64) {
382         var d int64
383         var e int64
384         var divr int64 = -1
385         if divd > -9223372036854775808 {
386                 d = divd / divr // amd64:-"JMP"
387                 e = divd % divr // amd64:-"JMP"
388                 d += e
389         }
390         return d, e
391 }
392
393 func NoFix32A(divr int32) (int32, int32) {
394         var d int32 = 42
395         var e int32 = 84
396         if divr > 5 {
397                 // amd64:-"JMP"
398                 // 386:-"JMP"
399                 d /= divr
400                 // amd64:-"JMP"
401                 // 386:-"JMP"
402                 e %= divr
403                 d += e
404         }
405         return d, e
406 }
407
408 func NoFix32B(divd int32) (int32, int32) {
409         var d int32
410         var e int32
411         var divr int32 = -1
412         if divd > -2147483648 {
413                 // amd64:-"JMP"
414                 // 386:-"JMP"
415                 d = divd / divr
416                 // amd64:-"JMP"
417                 // 386:-"JMP"
418                 e = divd % divr
419                 d += e
420         }
421         return d, e
422 }
423
424 func NoFix16A(divr int16) (int16, int16) {
425         var d int16 = 42
426         var e int16 = 84
427         if divr > 5 {
428                 // amd64:-"JMP"
429                 // 386:-"JMP"
430                 d /= divr
431                 // amd64:-"JMP"
432                 // 386:-"JMP"
433                 e %= divr
434                 d += e
435         }
436         return d, e
437 }
438
439 func NoFix16B(divd int16) (int16, int16) {
440         var d int16
441         var e int16
442         var divr int16 = -1
443         if divd > -32768 {
444                 // amd64:-"JMP"
445                 // 386:-"JMP"
446                 d = divd / divr
447                 // amd64:-"JMP"
448                 // 386:-"JMP"
449                 e = divd % divr
450                 d += e
451         }
452         return d, e
453 }
454
455 // Check that len() and cap() calls divided by powers of two are
456 // optimized into shifts and ands
457
458 func LenDiv1(a []int) int {
459         // 386:"SHRL\t[$]10"
460         // amd64:"SHRQ\t[$]10"
461         // arm64:"LSR\t[$]10",-"SDIV"
462         // arm:"SRL\t[$]10",-".*udiv"
463         // ppc64x:"SRD"\t[$]10"
464         return len(a) / 1024
465 }
466
467 func LenDiv2(s string) int {
468         // 386:"SHRL\t[$]11"
469         // amd64:"SHRQ\t[$]11"
470         // arm64:"LSR\t[$]11",-"SDIV"
471         // arm:"SRL\t[$]11",-".*udiv"
472         // ppc64x:"SRD\t[$]11"
473         return len(s) / (4097 >> 1)
474 }
475
476 func LenMod1(a []int) int {
477         // 386:"ANDL\t[$]1023"
478         // amd64:"ANDL\t[$]1023"
479         // arm64:"AND\t[$]1023",-"SDIV"
480         // arm/6:"AND",-".*udiv"
481         // arm/7:"BFC",-".*udiv",-"AND"
482         // ppc64x:"RLDICL"
483         return len(a) % 1024
484 }
485
486 func LenMod2(s string) int {
487         // 386:"ANDL\t[$]2047"
488         // amd64:"ANDL\t[$]2047"
489         // arm64:"AND\t[$]2047",-"SDIV"
490         // arm/6:"AND",-".*udiv"
491         // arm/7:"BFC",-".*udiv",-"AND"
492         // ppc64x:"RLDICL"
493         return len(s) % (4097 >> 1)
494 }
495
496 func CapDiv(a []int) int {
497         // 386:"SHRL\t[$]12"
498         // amd64:"SHRQ\t[$]12"
499         // arm64:"LSR\t[$]12",-"SDIV"
500         // arm:"SRL\t[$]12",-".*udiv"
501         // ppc64x:"SRD\t[$]12"
502         return cap(a) / ((1 << 11) + 2048)
503 }
504
505 func CapMod(a []int) int {
506         // 386:"ANDL\t[$]4095"
507         // amd64:"ANDL\t[$]4095"
508         // arm64:"AND\t[$]4095",-"SDIV"
509         // arm/6:"AND",-".*udiv"
510         // arm/7:"BFC",-".*udiv",-"AND"
511         // ppc64x:"RLDICL"
512         return cap(a) % ((1 << 11) + 2048)
513 }
514
515 func AddMul(x int) int {
516         // amd64:"LEAQ\t1"
517         return 2*x + 1
518 }
519
520 func MULA(a, b, c uint32) (uint32, uint32, uint32) {
521         // arm:`MULA`,-`MUL\s`
522         // arm64:`MADDW`,-`MULW`
523         r0 := a*b + c
524         // arm:`MULA`,-`MUL\s`
525         // arm64:`MADDW`,-`MULW`
526         r1 := c*79 + a
527         // arm:`ADD`,-`MULA`,-`MUL\s`
528         // arm64:`ADD`,-`MADD`,-`MULW`
529         // ppc64x:`ADD`,-`MULLD`
530         r2 := b*64 + c
531         return r0, r1, r2
532 }
533
534 func MULS(a, b, c uint32) (uint32, uint32, uint32) {
535         // arm/7:`MULS`,-`MUL\s`
536         // arm/6:`SUB`,`MUL\s`,-`MULS`
537         // arm64:`MSUBW`,-`MULW`
538         r0 := c - a*b
539         // arm/7:`MULS`,-`MUL\s`
540         // arm/6:`SUB`,`MUL\s`,-`MULS`
541         // arm64:`MSUBW`,-`MULW`
542         r1 := a - c*79
543         // arm/7:`SUB`,-`MULS`,-`MUL\s`
544         // arm64:`SUB`,-`MSUBW`,-`MULW`
545         // ppc64x:`SUB`,-`MULLD`
546         r2 := c - b*64
547         return r0, r1, r2
548 }
549
550 func addSpecial(a, b, c uint32) (uint32, uint32, uint32) {
551         // amd64:`INCL`
552         a++
553         // amd64:`DECL`
554         b--
555         // amd64:`SUBL.*-128`
556         c += 128
557         return a, b, c
558 }
559
560 // Divide -> shift rules usually require fixup for negative inputs.
561 // If the input is non-negative, make sure the fixup is eliminated.
562 func divInt(v int64) int64 {
563         if v < 0 {
564                 return 0
565         }
566         // amd64:-`.*SARQ.*63,`, -".*SHRQ", ".*SARQ.*[$]9,"
567         return v / 512
568 }
569
570 // The reassociate rules "x - (z + C) -> (x - z) - C" and
571 // "(z + C) -x -> C + (z - x)" can optimize the following cases.
572 func constantFold1(i0, j0, i1, j1, i2, j2, i3, j3 int) (int, int, int, int) {
573         // arm64:"SUB","ADD\t[$]2"
574         // ppc64x:"SUB","ADD\t[$]2"
575         r0 := (i0 + 3) - (j0 + 1)
576         // arm64:"SUB","SUB\t[$]4"
577         // ppc64x:"SUB","ADD\t[$]-4"
578         r1 := (i1 - 3) - (j1 + 1)
579         // arm64:"SUB","ADD\t[$]4"
580         // ppc64x:"SUB","ADD\t[$]4"
581         r2 := (i2 + 3) - (j2 - 1)
582         // arm64:"SUB","SUB\t[$]2"
583         // ppc64x:"SUB","ADD\t[$]-2"
584         r3 := (i3 - 3) - (j3 - 1)
585         return r0, r1, r2, r3
586 }
587
588 // The reassociate rules "x - (z + C) -> (x - z) - C" and
589 // "(C - z) - x -> C - (z + x)" can optimize the following cases.
590 func constantFold2(i0, j0, i1, j1 int) (int, int) {
591         // arm64:"ADD","MOVD\t[$]2","SUB"
592         // ppc64x: `SUBC\tR[0-9]+,\s[$]2,\sR`
593         r0 := (3 - i0) - (j0 + 1)
594         // arm64:"ADD","MOVD\t[$]4","SUB"
595         // ppc64x: `SUBC\tR[0-9]+,\s[$]4,\sR`
596         r1 := (3 - i1) - (j1 - 1)
597         return r0, r1
598 }
599
600 func constantFold3(i, j int) int {
601         // arm64: "MOVD\t[$]30","MUL",-"ADD",-"LSL"
602         // ppc64x:"MULLD\t[$]30","MULLD"
603         r := (5 * i) * (6 * j)
604         return r
605 }