github.com/sandwichdev/go-internals@v0.0.0-20210605002614-12311ac6b2c5/bytealg/index_amd64.s (about) 1 // Copyright 2018 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 #include "go_asm.h" 6 #include "textflag.h" 7 8 TEXT ·Index(SB),NOSPLIT,$0-56 9 MOVQ a_base+0(FP), DI 10 MOVQ a_len+8(FP), DX 11 MOVQ b_base+24(FP), R8 12 MOVQ b_len+32(FP), AX 13 MOVQ DI, R10 14 LEAQ ret+48(FP), R11 15 JMP indexbody<>(SB) 16 17 TEXT ·IndexString(SB),NOSPLIT,$0-40 18 MOVQ a_base+0(FP), DI 19 MOVQ a_len+8(FP), DX 20 MOVQ b_base+16(FP), R8 21 MOVQ b_len+24(FP), AX 22 MOVQ DI, R10 23 LEAQ ret+32(FP), R11 24 JMP indexbody<>(SB) 25 26 // AX: length of string, that we are searching for 27 // DX: length of string, in which we are searching 28 // DI: pointer to string, in which we are searching 29 // R8: pointer to string, that we are searching for 30 // R11: address, where to put return value 31 // Note: We want len in DX and AX, because PCMPESTRI implicitly consumes them 32 TEXT indexbody<>(SB),NOSPLIT,$0 33 CMPQ AX, DX 34 JA fail 35 CMPQ DX, $16 36 JAE sse42 37 no_sse42: 38 CMPQ AX, $2 39 JA _3_or_more 40 MOVW (R8), R8 41 LEAQ -1(DI)(DX*1), DX 42 loop2: 43 MOVW (DI), SI 44 CMPW SI,R8 45 JZ success 46 ADDQ $1,DI 47 CMPQ DI,DX 48 JB loop2 49 JMP fail 50 _3_or_more: 51 CMPQ AX, $3 52 JA _4_or_more 53 MOVW 1(R8), BX 54 MOVW (R8), R8 55 LEAQ -2(DI)(DX*1), DX 56 loop3: 57 MOVW (DI), SI 58 CMPW SI,R8 59 JZ partial_success3 60 ADDQ $1,DI 61 CMPQ DI,DX 62 JB loop3 63 JMP fail 64 partial_success3: 65 MOVW 1(DI), SI 66 CMPW SI,BX 67 JZ success 68 ADDQ $1,DI 69 CMPQ DI,DX 70 JB loop3 71 JMP fail 72 _4_or_more: 73 CMPQ AX, $4 74 JA _5_or_more 75 MOVL (R8), R8 76 LEAQ -3(DI)(DX*1), DX 77 loop4: 78 MOVL (DI), SI 79 CMPL SI,R8 80 JZ success 81 ADDQ $1,DI 82 CMPQ DI,DX 83 JB loop4 84 JMP fail 85 _5_or_more: 86 CMPQ AX, $7 87 JA _8_or_more 88 LEAQ 1(DI)(DX*1), DX 89 SUBQ AX, DX 90 MOVL -4(R8)(AX*1), BX 91 MOVL (R8), R8 92 loop5to7: 93 MOVL (DI), SI 94 CMPL SI,R8 95 JZ partial_success5to7 96 ADDQ $1,DI 97 CMPQ DI,DX 98 JB loop5to7 99 JMP fail 100 partial_success5to7: 101 MOVL -4(AX)(DI*1), SI 102 CMPL SI,BX 103 JZ success 104 ADDQ $1,DI 105 CMPQ DI,DX 106 JB loop5to7 107 JMP fail 108 _8_or_more: 109 CMPQ AX, $8 110 JA _9_or_more 111 MOVQ (R8), R8 112 LEAQ -7(DI)(DX*1), DX 113 loop8: 114 MOVQ (DI), SI 115 CMPQ SI,R8 116 JZ success 117 ADDQ $1,DI 118 CMPQ DI,DX 119 JB loop8 120 JMP fail 121 _9_or_more: 122 CMPQ AX, $15 123 JA _16_or_more 124 LEAQ 1(DI)(DX*1), DX 125 SUBQ AX, DX 126 MOVQ -8(R8)(AX*1), BX 127 MOVQ (R8), R8 128 loop9to15: 129 MOVQ (DI), SI 130 CMPQ SI,R8 131 JZ partial_success9to15 132 ADDQ $1,DI 133 CMPQ DI,DX 134 JB loop9to15 135 JMP fail 136 partial_success9to15: 137 MOVQ -8(AX)(DI*1), SI 138 CMPQ SI,BX 139 JZ success 140 ADDQ $1,DI 141 CMPQ DI,DX 142 JB loop9to15 143 JMP fail 144 _16_or_more: 145 CMPQ AX, $16 146 JA _17_or_more 147 MOVOU (R8), X1 148 LEAQ -15(DI)(DX*1), DX 149 loop16: 150 MOVOU (DI), X2 151 PCMPEQB X1, X2 152 PMOVMSKB X2, SI 153 CMPQ SI, $0xffff 154 JE success 155 ADDQ $1,DI 156 CMPQ DI,DX 157 JB loop16 158 JMP fail 159 _17_or_more: 160 CMPQ AX, $31 161 JA _32_or_more 162 LEAQ 1(DI)(DX*1), DX 163 SUBQ AX, DX 164 MOVOU -16(R8)(AX*1), X0 165 MOVOU (R8), X1 166 loop17to31: 167 MOVOU (DI), X2 168 PCMPEQB X1,X2 169 PMOVMSKB X2, SI 170 CMPQ SI, $0xffff 171 JE partial_success17to31 172 ADDQ $1,DI 173 CMPQ DI,DX 174 JB loop17to31 175 JMP fail 176 partial_success17to31: 177 MOVOU -16(AX)(DI*1), X3 178 PCMPEQB X0, X3 179 PMOVMSKB X3, SI 180 CMPQ SI, $0xffff 181 JE success 182 ADDQ $1,DI 183 CMPQ DI,DX 184 JB loop17to31 185 JMP fail 186 // We can get here only when AVX2 is enabled and cutoff for indexShortStr is set to 63 187 // So no need to check cpuid 188 _32_or_more: 189 CMPQ AX, $32 190 JA _33_to_63 191 VMOVDQU (R8), Y1 192 LEAQ -31(DI)(DX*1), DX 193 loop32: 194 VMOVDQU (DI), Y2 195 VPCMPEQB Y1, Y2, Y3 196 VPMOVMSKB Y3, SI 197 CMPL SI, $0xffffffff 198 JE success_avx2 199 ADDQ $1,DI 200 CMPQ DI,DX 201 JB loop32 202 JMP fail_avx2 203 _33_to_63: 204 LEAQ 1(DI)(DX*1), DX 205 SUBQ AX, DX 206 VMOVDQU -32(R8)(AX*1), Y0 207 VMOVDQU (R8), Y1 208 loop33to63: 209 VMOVDQU (DI), Y2 210 VPCMPEQB Y1, Y2, Y3 211 VPMOVMSKB Y3, SI 212 CMPL SI, $0xffffffff 213 JE partial_success33to63 214 ADDQ $1,DI 215 CMPQ DI,DX 216 JB loop33to63 217 JMP fail_avx2 218 partial_success33to63: 219 VMOVDQU -32(AX)(DI*1), Y3 220 VPCMPEQB Y0, Y3, Y4 221 VPMOVMSKB Y4, SI 222 CMPL SI, $0xffffffff 223 JE success_avx2 224 ADDQ $1,DI 225 CMPQ DI,DX 226 JB loop33to63 227 fail_avx2: 228 VZEROUPPER 229 fail: 230 MOVQ $-1, (R11) 231 RET 232 success_avx2: 233 VZEROUPPER 234 JMP success 235 sse42: 236 CMPB internal∕cpu·X86+const_offsetX86HasSSE42(SB), $1 237 JNE no_sse42 238 CMPQ AX, $12 239 // PCMPESTRI is slower than normal compare, 240 // so using it makes sense only if we advance 4+ bytes per compare 241 // This value was determined experimentally and is the ~same 242 // on Nehalem (first with SSE42) and Haswell. 243 JAE _9_or_more 244 LEAQ 16(R8), SI 245 TESTW $0xff0, SI 246 JEQ no_sse42 247 MOVOU (R8), X1 248 LEAQ -15(DI)(DX*1), SI 249 MOVQ $16, R9 250 SUBQ AX, R9 // We advance by 16-len(sep) each iteration, so precalculate it into R9 251 loop_sse42: 252 // 0x0c means: unsigned byte compare (bits 0,1 are 00) 253 // for equality (bits 2,3 are 11) 254 // result is not masked or inverted (bits 4,5 are 00) 255 // and corresponds to first matching byte (bit 6 is 0) 256 PCMPESTRI $0x0c, (DI), X1 257 // CX == 16 means no match, 258 // CX > R9 means partial match at the end of the string, 259 // otherwise sep is at offset CX from X1 start 260 CMPQ CX, R9 261 JBE sse42_success 262 ADDQ R9, DI 263 CMPQ DI, SI 264 JB loop_sse42 265 PCMPESTRI $0x0c, -1(SI), X1 266 CMPQ CX, R9 267 JA fail 268 LEAQ -1(SI), DI 269 sse42_success: 270 ADDQ CX, DI 271 success: 272 SUBQ R10, DI 273 MOVQ DI, (R11) 274 RET