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