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