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.
11 // This file contains code generation tests related to the comparison
18 // Check that compare to constant string use 2/4/8 byte compares
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.*, [$]`
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.*, [$]`
36 func CompareString3(s string) bool {
37 // amd64:`CMPQ\t\(.*\), [A-Z]`
41 return s == "xxxxxxxx"
44 // Check that arrays compare use 2/4/8 byte compares
46 func CompareArray1(a, b [2]byte) bool {
47 // amd64:`CMPW\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
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]`
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]`
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]`
72 func CompareArray5(a, b [15]byte) bool {
73 // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
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))
86 // Check that some structs generate 2/4/8 byte compares.
92 func CompareStruct1(s1, s2 T1) bool {
93 // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
102 func CompareStruct2(s1, s2 T2) bool {
103 // amd64:`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
108 // Assert that a memequal call is still generated when
109 // inlining would increase binary size too much.
115 func CompareStruct3(s1, s2 T3) bool {
116 // amd64:-`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
125 func CompareStruct4(s1, s2 T4) bool {
126 // amd64:-`CMPQ\tcommand-line-arguments[.+_a-z0-9]+\(SP\), [A-Z]`
135 // Test that LEAQ/ADDQconst are folded into SETx ops
139 func CmpFold(x uint32) {
140 // amd64:`SETHI\t.*\(SB\)`
144 // Test that direct comparisons with memory are generated when
147 func CmpMem1(p int, q *int) bool {
148 // amd64:`CMPQ\t\(.*\), [A-Z]`
152 func CmpMem2(p *int, q int) bool {
153 // amd64:`CMPQ\t\(.*\), [A-Z]`
157 func CmpMem3(p *int) bool {
158 // amd64:`CMPQ\t\(.*\), [$]7`
162 func CmpMem4(p *int) bool {
163 // amd64:`CMPQ\t\(.*\), [$]7`
167 func CmpMem5(p **int) {
168 // amd64:`CMPL\truntime.writeBarrier\(SB\), [$]0`
172 func CmpMem6(a []int) int {
173 // 386:`CMPL\s8\([A-Z]+\),`
174 // amd64:`CMPQ\s16\([A-Z]+\),`
182 // Check tbz/tbnz are generated when comparing against zero on arm64
184 func CmpZero1(a int32, ptr *int) {
185 if a < 0 { // arm64:"TBZ"
190 func CmpZero2(a int64, ptr *int) {
191 if a < 0 { // arm64:"TBZ"
196 func CmpZero3(a int32, ptr *int) {
197 if a >= 0 { // arm64:"TBNZ"
202 func CmpZero4(a int64, ptr *int) {
203 if a >= 0 { // arm64:"TBNZ"
208 func CmpToZero(a, b, d int32, e, f int64, deOptC0, deOptC1 bool) int32 {
210 // arm64:`TSTW`,-`AND`
211 // 386:`TESTL`,-`ANDL`
212 // amd64:`TESTL`,-`ANDL`
215 // arm64:`CMNW`,-`ADD`
219 // arm64:`TST`,-`AND`
220 // amd64:`TESTQ`,-`ANDQ`
222 // arm64:`CMN`,-`ADD`
224 // not optimized to single CMNW/CMN due to further use of b+d
225 // arm64:`ADD`,-`CMNW`
228 // not optimized to single TSTW/TST due to further use of a&d
229 // arm64:`AND`,-`TSTW`
233 // arm64:`TST\sR[0-9]+<<3,\sR[0-9]+`
235 // arm64:`CMN\sR[0-9]+<<3,\sR[0-9]+`
237 // arm64:`TST\sR[0-9],\sR[0-9]+`
268 func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
270 // ppc64x:"ANDCC",-"CMPW"
271 // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
276 // ppc64x:"ANDCC",-"CMP"
277 // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
282 // ppc64x:"ANDCC",-"CMP"
283 // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
287 // ppc64x:"ORCC",-"CMP"
288 // wasm:"I64Eqz",-"I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
293 // ppc64x:"XORCC",-"CMP"
294 // wasm:"I64Eqz","I32Eqz",-"I64ExtendI32U",-"I32WrapI64"
301 // The following CmpToZero_ex* check that cmp|cmn with bmi|bpl are generated for
302 // 'comparing to zero' expressions
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)`
313 // arm64:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
318 // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
323 // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
333 // arm64:`SUB`,`CMP`,`BGT`
338 // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
339 // arm:`CMN`,-`ADD`,`(BMI|BPL)`
344 // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
345 // arm:`CMN`,-`ADD`,`(BMI|BPL)`
350 // arm64:`CMPW|CMNW`,`(BMI|BPL)`
351 // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
356 // arm64:`SUB`,`TBNZ`
357 // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
366 // TODO: optimize 'var - var'
367 func CmpToZero_ex2(a, b, c int64, e, f, g int32) int {
368 // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
373 // arm64:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
378 // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
383 // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
384 // arm:`CMN`,-`ADD`,`(BMI|BPL)`
389 // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
390 // arm:`CMN`,-`ADD`,`(BMI|BPL)`
398 func CmpToZero_ex3(a, b, c, d int64, e, f, g, h int32) int {
399 // arm64:`CMN`,-`MADD`,`MUL`,`(BMI|BPL)`
404 // arm64:`CMN`,-`MADD`,`MUL`,`(BMI|BPL)`
409 // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
410 // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
415 // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
416 // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
424 func CmpToZero_ex4(a, b, c, d int64, e, f, g, h int32) int {
425 // arm64:`CMP`,-`MSUB`,`MUL`,`BEQ`,`(BMI|BPL)`
430 // arm64:`CMP`,-`MSUB`,`MUL`,`(BMI|BPL)`
435 // arm64:`CMPW`,-`MSUBW`,`MULW`,`(BMI|BPL)`
440 // arm64:`CMPW`,-`MSUBW`,`MULW`,`(BMI|BPL)`
447 func CmpToZero_ex5(e, f int32, u uint32) int {
448 // arm:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
453 // arm:`CMP`,-`SUB`,`(BMI|BPL)`
454 if f-int32(u>>2) >= 0 {
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 {
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 {
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 {
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 {
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 {
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 {
510 func CmpToZeroU_ex1(a uint8, b uint16, c uint32, d uint64) int {
511 // wasm:"I64Eqz"-"I64LtU"
515 // wasm:"I64Eqz"-"I64LtU"
519 // wasm:"I64Eqz"-"I64LtU"
523 // wasm:"I64Eqz"-"I64LtU"
530 func CmpToZeroU_ex2(a uint8, b uint16, c uint32, d uint64) int {
531 // wasm:"I64Eqz"-"I64LeU"
535 // wasm:"I64Eqz"-"I64LeU"
539 // wasm:"I64Eqz"-"I64LeU"
543 // wasm:"I64Eqz"-"I64LeU"
550 func CmpToOneU_ex1(a uint8, b uint16, c uint32, d uint64) int {
551 // wasm:"I64Eqz"-"I64LtU"
555 // wasm:"I64Eqz"-"I64LtU"
559 // wasm:"I64Eqz"-"I64LtU"
563 // wasm:"I64Eqz"-"I64LtU"
570 func CmpToOneU_ex2(a uint8, b uint16, c uint32, d uint64) int {
571 // wasm:"I64Eqz"-"I64LeU"
575 // wasm:"I64Eqz"-"I64LeU"
579 // wasm:"I64Eqz"-"I64LeU"
583 // wasm:"I64Eqz"-"I64LeU"
590 // Check that small memequals are replaced with eq instructions
592 func equalConstString1() bool {
595 // amd64:-".*memequal"
596 // arm64:-".*memequal"
597 // ppc64x:-".*memequal"
601 func equalVarString1(a string) bool {
603 // amd64:-".*memequal"
604 // arm64:-".*memequal"
605 // ppc64x:-".*memequal"
609 func equalConstString2() bool {
612 // amd64:-".*memequal"
613 // arm64:-".*memequal"
614 // ppc64x:-".*memequal"
618 func equalVarString2(a string) bool {
620 // amd64:-".*memequal"
621 // arm64:-".*memequal"
622 // ppc64x:-".*memequal"
626 func equalConstString4() bool {
629 // amd64:-".*memequal"
630 // arm64:-".*memequal"
631 // ppc64x:-".*memequal"
635 func equalVarString4(a string) bool {
637 // amd64:-".*memequal"
638 // arm64:-".*memequal"
639 // ppc64x:-".*memequal"
643 func equalConstString8() bool {
644 a := string("AAAAAAAA")
645 b := string("ZZZZZZZZ")
646 // amd64:-".*memequal"
647 // arm64:-".*memequal"
648 // ppc64x:-".*memequal"
652 func equalVarString8(a string) bool {
653 b := string("ZZZZZZZZ")
654 // amd64:-".*memequal"
655 // arm64:-".*memequal"
656 // ppc64x:-".*memequal"
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`
666 // arm64:`CMN`,-`CMP`
670 // arm64:`CMN`,-`CMP`
674 // arm64:`CMN`,-`CMP`
678 // arm64:`CMN`,-`CMP`
682 // arm64:`CMN`,-`CMP`
686 // arm64:`CMN`,-`CMP`
690 // arm64:`CMN`,-`CMP`
694 // arm64:`CMN`,-`CMP`
698 // arm64:`CMP`,-`CMN`
702 // arm64:`CMP`,-`CMN`
706 return c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9 + c10 + c11
709 func cmpToCmnLessThan(a, b, c, d int) int {
710 var c1, c2, c3, c4 int
711 // arm64:`CMN`,`CSET\tMI`,-`CMP`
715 // arm64:`CMN`,`CSET\tMI`,-`CMP`
719 // arm64:`CMN`,`CSET\tMI`,-`CMP`
723 // arm64:`CMP`,`CSET\tMI`,-`CMN`
727 return c1 + c2 + c3 + c4
730 func cmpToCmnGreaterThanEqual(a, b, c, d int) int {
731 var c1, c2, c3, c4 int
732 // arm64:`CMN`,`CSET\tPL`,-`CMP`
736 // arm64:`CMN`,`CSET\tPL`,-`CMP`
740 // arm64:`CMN`,`CSET\tPL`,-`CMP`
744 // arm64:`CMP`,`CSET\tPL`,-`CMN`
748 return c1 + c2 + c3 + c4
751 func cmp1(val string) bool {
753 // amd64:-".*memequal"
757 func cmp2(val string) bool {
759 // amd64:-".*memequal"
763 func cmp3(val string) bool {
765 // amd64:-".*memequal"
769 func cmp4(val string) bool {
771 // amd64:-".*memequal"
775 func cmp5[T comparable](val T) bool {
777 // amd64:-".*memequal"
781 func cmp6[T comparable](val T) bool {
783 // amd64:-".*memequal"
788 cmp5[string]("") // force instantiation
789 cmp6[string]("") // force instantiation