]> Cypherpunks.ru repositories - gostls13.git/blob - test/codegen/comparisons.go
cmd/compile: optimize absorbing InvertFlags into Noov comparisons for arm64
[gostls13.git] / test / codegen / comparisons.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 import "unsafe"
10
11 // This file contains code generation tests related to the comparison
12 // operators.
13
14 // -------------- //
15 //    Equality    //
16 // -------------- //
17
18 // Check that compare to constant string use 2/4/8 byte compares
19
20 func CompareString1(s string) bool {
21         // amd64:`CMPW\t\(.*\), [$]`
22         // arm64:`MOVHU\t\(.*\), [R]`,`MOVD\t[$]`,`CMPW\tR`
23         // ppc64le:`MOVHZ\t\(.*\), [R]`,`CMPW\t.*, [$]`
24         // s390x:`MOVHBR\t\(.*\), [R]`,`CMPW\t.*, [$]`
25         return s == "xx"
26 }
27
28 func CompareString2(s string) bool {
29         // amd64:`CMPL\t\(.*\), [$]`
30         // arm64:`MOVWU\t\(.*\), [R]`,`CMPW\t.*, [R]`
31         // ppc64le:`MOVWZ\t\(.*\), [R]`,`CMPW\t.*, [R]`
32         // s390x:`MOVWBR\t\(.*\), [R]`,`CMPW\t.*, [$]`
33         return s == "xxxx"
34 }
35
36 func CompareString3(s string) bool {
37         // amd64:`CMPQ\t\(.*\), [A-Z]`
38         // arm64:-`CMPW\t`
39         // ppc64x:-`CMPW\t`
40         // s390x:-`CMPW\t`
41         return s == "xxxxxxxx"
42 }
43
44 // Check that arrays compare use 2/4/8 byte compares
45
46 func CompareArray1(a, b [2]byte) bool {
47         // amd64:`CMPW\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
48         // arm64:-`MOVBU\t`
49         // ppc64le:-`MOVBZ\t`
50         // s390x:-`MOVBZ\t`
51         return a == b
52 }
53
54 func CompareArray2(a, b [3]uint16) bool {
55         // amd64:`CMPL\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
56         // amd64:`CMPW\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
57         return a == b
58 }
59
60 func CompareArray3(a, b [3]int16) bool {
61         // amd64:`CMPL\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
62         // amd64:`CMPW\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
63         return a == b
64 }
65
66 func CompareArray4(a, b [12]int8) bool {
67         // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
68         // amd64:`CMPL\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
69         return a == b
70 }
71
72 func CompareArray5(a, b [15]byte) bool {
73         // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
74         return a == b
75 }
76
77 // This was a TODO in mapaccess1_faststr
78 func CompareArray6(a, b unsafe.Pointer) bool {
79         // amd64:`CMPL\t\(.*\), [A-Z]`
80         // arm64:`MOVWU\t\(.*\), [R]`,`CMPW\t.*, [R]`
81         // ppc64le:`MOVWZ\t\(.*\), [R]`,`CMPW\t.*, [R]`
82         // s390x:`MOVWBR\t\(.*\), [R]`,`CMPW\t.*, [R]`
83         return *((*[4]byte)(a)) != *((*[4]byte)(b))
84 }
85
86 // Check that some structs generate 2/4/8 byte compares.
87
88 type T1 struct {
89         a [8]byte
90 }
91
92 func CompareStruct1(s1, s2 T1) bool {
93         // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
94         // amd64:-`CALL`
95         return s1 == s2
96 }
97
98 type T2 struct {
99         a [16]byte
100 }
101
102 func CompareStruct2(s1, s2 T2) bool {
103         // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
104         // amd64:-`CALL`
105         return s1 == s2
106 }
107
108 // Assert that a memequal call is still generated when
109 // inlining would increase binary size too much.
110
111 type T3 struct {
112         a [24]byte
113 }
114
115 func CompareStruct3(s1, s2 T3) bool {
116         // amd64:-`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
117         // amd64:`CALL`
118         return s1 == s2
119 }
120
121 type T4 struct {
122         a [32]byte
123 }
124
125 func CompareStruct4(s1, s2 T4) bool {
126         // amd64:-`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
127         // amd64:`CALL`
128         return s1 == s2
129 }
130
131 // -------------- //
132 //    Ordering    //
133 // -------------- //
134
135 // Test that LEAQ/ADDQconst are folded into SETx ops
136
137 var r bool
138
139 func CmpFold(x uint32) {
140         // amd64:`SETHI\t.*\(SB\)`
141         r = x > 4
142 }
143
144 // Test that direct comparisons with memory are generated when
145 // possible
146
147 func CmpMem1(p int, q *int) bool {
148         // amd64:`CMPQ\t\(.*\), [A-Z]`
149         return p < *q
150 }
151
152 func CmpMem2(p *int, q int) bool {
153         // amd64:`CMPQ\t\(.*\), [A-Z]`
154         return *p < q
155 }
156
157 func CmpMem3(p *int) bool {
158         // amd64:`CMPQ\t\(.*\), [$]7`
159         return *p < 7
160 }
161
162 func CmpMem4(p *int) bool {
163         // amd64:`CMPQ\t\(.*\), [$]7`
164         return 7 < *p
165 }
166
167 func CmpMem5(p **int) {
168         // amd64:`CMPL\truntime.writeBarrier\(SB\), [$]0`
169         *p = nil
170 }
171
172 func CmpMem6(a []int) int {
173         // 386:`CMPL\s8\([A-Z]+\),`
174         // amd64:`CMPQ\s16\([A-Z]+\),`
175         if a[1] > a[2] {
176                 return 1
177         } else {
178                 return 2
179         }
180 }
181
182 // Check tbz/tbnz are generated when comparing against zero on arm64
183
184 func CmpZero1(a int32, ptr *int) {
185         if a < 0 { // arm64:"TBZ"
186                 *ptr = 0
187         }
188 }
189
190 func CmpZero2(a int64, ptr *int) {
191         if a < 0 { // arm64:"TBZ"
192                 *ptr = 0
193         }
194 }
195
196 func CmpZero3(a int32, ptr *int) {
197         if a >= 0 { // arm64:"TBNZ"
198                 *ptr = 0
199         }
200 }
201
202 func CmpZero4(a int64, ptr *int) {
203         if a >= 0 { // arm64:"TBNZ"
204                 *ptr = 0
205         }
206 }
207
208 func CmpToZero(a, b, d int32, e, f int64, deOptC0, deOptC1 bool) int32 {
209         // arm:`TST`,-`AND`
210         // arm64:`TSTW`,-`AND`
211         // 386:`TESTL`,-`ANDL`
212         // amd64:`TESTL`,-`ANDL`
213         c0 := a&b < 0
214         // arm:`CMN`,-`ADD`
215         // arm64:`CMNW`,-`ADD`
216         c1 := a+b < 0
217         // arm:`TEQ`,-`XOR`
218         c2 := a^b < 0
219         // arm64:`TST`,-`AND`
220         // amd64:`TESTQ`,-`ANDQ`
221         c3 := e&f < 0
222         // arm64:`CMN`,-`ADD`
223         c4 := e+f < 0
224         // not optimized to single CMNW/CMN due to further use of b+d
225         // arm64:`ADD`,-`CMNW`
226         // arm:`ADD`,-`CMN`
227         c5 := b+d == 0
228         // not optimized to single TSTW/TST due to further use of a&d
229         // arm64:`AND`,-`TSTW`
230         // arm:`AND`,-`TST`
231         // 386:`ANDL`
232         c6 := a&d >= 0
233         // arm64:`TST\sR[0-9]+<<3,\sR[0-9]+`
234         c7 := e&(f<<3) < 0
235         // arm64:`CMN\sR[0-9]+<<3,\sR[0-9]+`
236         c8 := e+(f<<3) < 0
237         // arm64:`TST\sR[0-9],\sR[0-9]+`
238         c9 := e&(-19) < 0
239         if c0 {
240                 return 1
241         } else if c1 {
242                 return 2
243         } else if c2 {
244                 return 3
245         } else if c3 {
246                 return 4
247         } else if c4 {
248                 return 5
249         } else if c5 {
250                 return 6
251         } else if c6 {
252                 return 7
253         } else if c7 {
254                 return 9
255         } else if c8 {
256                 return 10
257         } else if c9 {
258                 return 11
259         } else if deOptC0 {
260                 return b + d
261         } else if deOptC1 {
262                 return a & d
263         } else {
264                 return 0
265         }
266 }
267
268 func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
269
270         // ppc64x:"ANDCC",-"CMPW"
271         // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
272         if a&63 == 0 {
273                 return 1
274         }
275
276         // ppc64x:"ANDCC",-"CMP"
277         // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
278         if d&255 == 0 {
279                 return 1
280         }
281
282         // ppc64x:"ANDCC",-"CMP"
283         // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
284         if d&e == 0 {
285                 return 1
286         }
287         // ppc64x:"ORCC",-"CMP"
288         // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
289         if d|e == 0 {
290                 return 1
291         }
292
293         // ppc64x:"XORCC",-"CMP"
294         // wasm:"I64Eqz","I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
295         if e^d == 0 {
296                 return 1
297         }
298         return 0
299 }
300
301 // The following CmpToZero_ex* check that cmp|cmn with bmi|bpl are generated for
302 // 'comparing to zero' expressions
303
304 // var + const
305 // 'x-const' might be canonicalized to 'x+(-const)', so we check both
306 // CMN and CMP for subtraction expressions to make the pattern robust.
307 func CmpToZero_ex1(a int64, e int32) int {
308         // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
309         if a+3 < 0 {
310                 return 1
311         }
312
313         // arm64:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
314         if a+5 <= 0 {
315                 return 1
316         }
317
318         // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
319         if a+13 >= 0 {
320                 return 2
321         }
322
323         // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
324         if a-7 < 0 {
325                 return 3
326         }
327
328         // arm64:`SUB`,`TBZ`
329         if a-11 >= 0 {
330                 return 4
331         }
332
333         // arm64:`SUB`,`CMP`,`BGT`
334         if a-19 > 0 {
335                 return 4
336         }
337
338         // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
339         // arm:`CMN`,-`ADD`,`(BMI|BPL)`
340         if e+3 < 0 {
341                 return 5
342         }
343
344         // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
345         // arm:`CMN`,-`ADD`,`(BMI|BPL)`
346         if e+13 >= 0 {
347                 return 6
348         }
349
350         // arm64:`CMPW|CMNW`,`(BMI|BPL)`
351         // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
352         if e-7 < 0 {
353                 return 7
354         }
355
356         // arm64:`SUB`,`TBNZ`
357         // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
358         if e-11 >= 0 {
359                 return 8
360         }
361
362         return 0
363 }
364
365 // var + var
366 // TODO: optimize 'var - var'
367 func CmpToZero_ex2(a, b, c int64, e, f, g int32) int {
368         // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
369         if a+b < 0 {
370                 return 1
371         }
372
373         // arm64:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
374         if a+c <= 0 {
375                 return 1
376         }
377
378         // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
379         if b+c >= 0 {
380                 return 2
381         }
382
383         // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
384         // arm:`CMN`,-`ADD`,`(BMI|BPL)`
385         if e+f < 0 {
386                 return 5
387         }
388
389         // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
390         // arm:`CMN`,-`ADD`,`(BMI|BPL)`
391         if f+g >= 0 {
392                 return 6
393         }
394         return 0
395 }
396
397 // var + var*var
398 func CmpToZero_ex3(a, b, c, d int64, e, f, g, h int32) int {
399         // arm64:`CMN`,-`MADD`,`MUL`,`(BMI|BPL)`
400         if a+b*c < 0 {
401                 return 1
402         }
403
404         // arm64:`CMN`,-`MADD`,`MUL`,`(BMI|BPL)`
405         if b+c*d >= 0 {
406                 return 2
407         }
408
409         // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
410         // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
411         if e+f*g > 0 {
412                 return 5
413         }
414
415         // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
416         // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
417         if f+g*h <= 0 {
418                 return 6
419         }
420         return 0
421 }
422
423 // var - var*var
424 func CmpToZero_ex4(a, b, c, d int64, e, f, g, h int32) int {
425         // arm64:`CMP`,-`MSUB`,`MUL`,`BEQ`,`(BMI|BPL)`
426         if a-b*c > 0 {
427                 return 1
428         }
429
430         // arm64:`CMP`,-`MSUB`,`MUL`,`(BMI|BPL)`
431         if b-c*d >= 0 {
432                 return 2
433         }
434
435         // arm64:`CMPW`,-`MSUBW`,`MULW`,`(BMI|BPL)`
436         if e-f*g < 0 {
437                 return 5
438         }
439
440         // arm64:`CMPW`,-`MSUBW`,`MULW`,`(BMI|BPL)`
441         if f-g*h >= 0 {
442                 return 6
443         }
444         return 0
445 }
446
447 func CmpToZero_ex5(e, f int32, u uint32) int {
448         // arm:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
449         if e+f<<1 > 0 {
450                 return 1
451         }
452
453         // arm:`CMP`,-`SUB`,`(BMI|BPL)`
454         if f-int32(u>>2) >= 0 {
455                 return 2
456         }
457         return 0
458 }
459
460 func UintLtZero(a uint8, b uint16, c uint32, d uint64) int {
461         // amd64: -`(TESTB|TESTW|TESTL|TESTQ|JCC|JCS)`
462         // arm64: -`(CMPW|CMP|BHS|BLO)`
463         if a < 0 || b < 0 || c < 0 || d < 0 {
464                 return 1
465         }
466         return 0
467 }
468
469 func UintGeqZero(a uint8, b uint16, c uint32, d uint64) int {
470         // amd64: -`(TESTB|TESTW|TESTL|TESTQ|JCS|JCC)`
471         // arm64: -`(CMPW|CMP|BLO|BHS)`
472         if a >= 0 || b >= 0 || c >= 0 || d >= 0 {
473                 return 1
474         }
475         return 0
476 }
477
478 func UintGtZero(a uint8, b uint16, c uint32, d uint64) int {
479         // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BLS|BHI)`
480         if a > 0 || b > 0 || c > 0 || d > 0 {
481                 return 1
482         }
483         return 0
484 }
485
486 func UintLeqZero(a uint8, b uint16, c uint32, d uint64) int {
487         // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BHI|BLS)`
488         if a <= 0 || b <= 0 || c <= 0 || d <= 0 {
489                 return 1
490         }
491         return 0
492 }
493
494 func UintLtOne(a uint8, b uint16, c uint32, d uint64) int {
495         // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BHS|BLO)`
496         if a < 1 || b < 1 || c < 1 || d < 1 {
497                 return 1
498         }
499         return 0
500 }
501
502 func UintGeqOne(a uint8, b uint16, c uint32, d uint64) int {
503         // arm64: `(CBN?ZW)`, `(CBN?Z[^W])`, -`(CMPW|CMP|BLO|BHS)`
504         if a >= 1 || b >= 1 || c >= 1 || d >= 1 {
505                 return 1
506         }
507         return 0
508 }
509
510 func CmpToZeroU_ex1(a uint8, b uint16, c uint32, d uint64) int {
511         // wasm:"I64Eqz"-"I64LtU"
512         if 0 < a {
513                 return 1
514         }
515         // wasm:"I64Eqz"-"I64LtU"
516         if 0 < b {
517                 return 1
518         }
519         // wasm:"I64Eqz"-"I64LtU"
520         if 0 < c {
521                 return 1
522         }
523         // wasm:"I64Eqz"-"I64LtU"
524         if 0 < d {
525                 return 1
526         }
527         return 0
528 }
529
530 func CmpToZeroU_ex2(a uint8, b uint16, c uint32, d uint64) int {
531         // wasm:"I64Eqz"-"I64LeU"
532         if a <= 0 {
533                 return 1
534         }
535         // wasm:"I64Eqz"-"I64LeU"
536         if b <= 0 {
537                 return 1
538         }
539         // wasm:"I64Eqz"-"I64LeU"
540         if c <= 0 {
541                 return 1
542         }
543         // wasm:"I64Eqz"-"I64LeU"
544         if d <= 0 {
545                 return 1
546         }
547         return 0
548 }
549
550 func CmpToOneU_ex1(a uint8, b uint16, c uint32, d uint64) int {
551         // wasm:"I64Eqz"-"I64LtU"
552         if a < 1 {
553                 return 1
554         }
555         // wasm:"I64Eqz"-"I64LtU"
556         if b < 1 {
557                 return 1
558         }
559         // wasm:"I64Eqz"-"I64LtU"
560         if c < 1 {
561                 return 1
562         }
563         // wasm:"I64Eqz"-"I64LtU"
564         if d < 1 {
565                 return 1
566         }
567         return 0
568 }
569
570 func CmpToOneU_ex2(a uint8, b uint16, c uint32, d uint64) int {
571         // wasm:"I64Eqz"-"I64LeU"
572         if 1 <= a {
573                 return 1
574         }
575         // wasm:"I64Eqz"-"I64LeU"
576         if 1 <= b {
577                 return 1
578         }
579         // wasm:"I64Eqz"-"I64LeU"
580         if 1 <= c {
581                 return 1
582         }
583         // wasm:"I64Eqz"-"I64LeU"
584         if 1 <= d {
585                 return 1
586         }
587         return 0
588 }
589
590 // Check that small memequals are replaced with eq instructions
591
592 func equalConstString1() bool {
593         a := string("A")
594         b := string("Z")
595         // amd64:-".*memequal"
596         // arm64:-".*memequal"
597         // ppc64x:-".*memequal"
598         return a == b
599 }
600
601 func equalVarString1(a string) bool {
602         b := string("Z")
603         // amd64:-".*memequal"
604         // arm64:-".*memequal"
605         // ppc64x:-".*memequal"
606         return a[:1] == b
607 }
608
609 func equalConstString2() bool {
610         a := string("AA")
611         b := string("ZZ")
612         // amd64:-".*memequal"
613         // arm64:-".*memequal"
614         // ppc64x:-".*memequal"
615         return a == b
616 }
617
618 func equalVarString2(a string) bool {
619         b := string("ZZ")
620         // amd64:-".*memequal"
621         // arm64:-".*memequal"
622         // ppc64x:-".*memequal"
623         return a[:2] == b
624 }
625
626 func equalConstString4() bool {
627         a := string("AAAA")
628         b := string("ZZZZ")
629         // amd64:-".*memequal"
630         // arm64:-".*memequal"
631         // ppc64x:-".*memequal"
632         return a == b
633 }
634
635 func equalVarString4(a string) bool {
636         b := string("ZZZZ")
637         // amd64:-".*memequal"
638         // arm64:-".*memequal"
639         // ppc64x:-".*memequal"
640         return a[:4] == b
641 }
642
643 func equalConstString8() bool {
644         a := string("AAAAAAAA")
645         b := string("ZZZZZZZZ")
646         // amd64:-".*memequal"
647         // arm64:-".*memequal"
648         // ppc64x:-".*memequal"
649         return a == b
650 }
651
652 func equalVarString8(a string) bool {
653         b := string("ZZZZZZZZ")
654         // amd64:-".*memequal"
655         // arm64:-".*memequal"
656         // ppc64x:-".*memequal"
657         return a[:8] == b
658 }
659
660 func cmpToCmn(a, b, c, d int) int {
661         var c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11 int
662         // arm64:`CMN`,-`CMP`
663         if a < -8 {
664                 c1 = 1
665         }
666         // arm64:`CMN`,-`CMP`
667         if a+1 == 0 {
668                 c2 = 1
669         }
670         // arm64:`CMN`,-`CMP`
671         if a+3 != 0 {
672                 c3 = 1
673         }
674         // arm64:`CMN`,-`CMP`
675         if a+b == 0 {
676                 c4 = 1
677         }
678         // arm64:`CMN`,-`CMP`
679         if b+c != 0 {
680                 c5 = 1
681         }
682         // arm64:`CMN`,-`CMP`
683         if a == -c {
684                 c6 = 1
685         }
686         // arm64:`CMN`,-`CMP`
687         if b != -d {
688                 c7 = 1
689         }
690         // arm64:`CMN`,-`CMP`
691         if a*b+c == 0 {
692                 c8 = 1
693         }
694         // arm64:`CMN`,-`CMP`
695         if a*c+b != 0 {
696                 c9 = 1
697         }
698         // arm64:`CMP`,-`CMN`
699         if b*c-a == 0 {
700                 c10 = 1
701         }
702         // arm64:`CMP`,-`CMN`
703         if a*d-b != 0 {
704                 c11 = 1
705         }
706         return c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9 + c10 + c11
707 }
708
709 func cmpToCmnLessThan(a, b, c, d int) int {
710         var c1, c2, c3, c4 int
711         // arm64:`CMN`,`CSET\tMI`,-`CMP`
712         if a+1 < 0 {
713                 c1 = 1
714         }
715         // arm64:`CMN`,`CSET\tMI`,-`CMP`
716         if a+b < 0 {
717                 c2 = 1
718         }
719         // arm64:`CMN`,`CSET\tMI`,-`CMP`
720         if a*b+c < 0 {
721                 c3 = 1
722         }
723         // arm64:`CMP`,`CSET\tMI`,-`CMN`
724         if a-b*c < 0 {
725                 c4 = 1
726         }
727         return c1 + c2 + c3 + c4
728 }
729
730 func cmpToCmnGreaterThanEqual(a, b, c, d int) int {
731         var c1, c2, c3, c4 int
732         // arm64:`CMN`,`CSET\tPL`,-`CMP`
733         if a+1 >= 0 {
734                 c1 = 1
735         }
736         // arm64:`CMN`,`CSET\tPL`,-`CMP`
737         if a+b >= 0 {
738                 c2 = 1
739         }
740         // arm64:`CMN`,`CSET\tPL`,-`CMP`
741         if a*b+c >= 0 {
742                 c3 = 1
743         }
744         // arm64:`CMP`,`CSET\tPL`,-`CMN`
745         if a-b*c >= 0 {
746                 c4 = 1
747         }
748         return c1 + c2 + c3 + c4
749 }
750
751 func cmp1(val string) bool {
752         var z string
753         // amd64:-".*memequal"
754         return z == val
755 }
756
757 func cmp2(val string) bool {
758         var z string
759         // amd64:-".*memequal"
760         return val == z
761 }
762
763 func cmp3(val string) bool {
764         z := "food"
765         // amd64:-".*memequal"
766         return z == val
767 }
768
769 func cmp4(val string) bool {
770         z := "food"
771         // amd64:-".*memequal"
772         return val == z
773 }
774
775 func cmp5[T comparable](val T) bool {
776         var z T
777         // amd64:-".*memequal"
778         return z == val
779 }
780
781 func cmp6[T comparable](val T) bool {
782         var z T
783         // amd64:-".*memequal"
784         return val == z
785 }
786
787 func cmp7() {
788         cmp5[string]("") // force instantiation
789         cmp6[string]("") // force instantiation
790 }
791
792 type Point struct {
793         X, Y int
794 }
795
796 // invertLessThanNoov checks (LessThanNoov (InvertFlags x)) is lowered as
797 // CMP, CSET, CSEL instruction sequence. InvertFlags are only generated under
798 // certain conditions, see canonLessThan, so if the code below does not
799 // generate an InvertFlags OP, this check may fail.
800 func invertLessThanNoov(p1, p2, p3 Point) bool {
801         // arm64:`CMP`,`CSET`,`CSEL`
802         return (p1.X-p3.X)*(p2.Y-p3.Y)-(p2.X-p3.X)*(p1.Y-p3.Y) < 0
803 }