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 b := 40 - a 89 return b 90 } 91 92 func SubFromConstNeg(a int) int { 93 // ppc64x: `ADD\t[$]40,\sR[0-9]+,\sR` 94 c := 40 - (-a) 95 return c 96 } 97 98 func SubSubFromConst(a int) int { 99 // ppc64x: `ADD\t[$]20,\sR[0-9]+,\sR` 100 c := 40 - (20 - a) 101 return c 102 } 103 104 func AddSubFromConst(a int) int { 105 // ppc64x: `SUBC\tR[0-9]+,\s[$]60,\sR` 106 c := 40 + (20 - a) 107 return c 108 } 109 110 func NegSubFromConst(a int) int { 111 // ppc64x: `ADD\t[$]-20,\sR[0-9]+,\sR` 112 c := -(20 - a) 113 return c 114 } 115 116 func NegAddFromConstNeg(a int) int { 117 // ppc64x: `SUBC\tR[0-9]+,\s[$]40,\sR` 118 c := -(-40 + a) 119 return c 120 } 121 122 func SubSubNegSimplify(a, b int) int { 123 // amd64:"NEGQ" 124 // ppc64x:"NEG" 125 r := (a - b) - a 126 return r 127 } 128 129 func SubAddSimplify(a, b int) int { 130 // amd64:-"SUBQ",-"ADDQ" 131 // ppc64x:-"SUB",-"ADD" 132 r := a + (b - a) 133 return r 134 } 135 136 func SubAddSimplify2(a, b, c int) (int, int, int, int, int, int) { 137 // amd64:-"ADDQ" 138 r := (a + b) - (a + c) 139 // amd64:-"ADDQ" 140 r1 := (a + b) - (c + a) 141 // amd64:-"ADDQ" 142 r2 := (b + a) - (a + c) 143 // amd64:-"ADDQ" 144 r3 := (b + a) - (c + a) 145 // amd64:-"SUBQ" 146 r4 := (a - c) + (c + b) 147 // amd64:-"SUBQ" 148 r5 := (a - c) + (b + c) 149 return r, r1, r2, r3, r4, r5 150 } 151 152 func SubAddNegSimplify(a, b int) int { 153 // amd64:"NEGQ",-"ADDQ",-"SUBQ" 154 // ppc64x:"NEG",-"ADD",-"SUB" 155 r := a - (b + a) 156 return r 157 } 158 159 func AddAddSubSimplify(a, b, c int) int { 160 // amd64:-"SUBQ" 161 // ppc64x:-"SUB" 162 r := a + (b + (c - a)) 163 return r 164 } 165 166 // -------------------- // 167 // Multiplication // 168 // -------------------- // 169 170 func Pow2Muls(n1, n2 int) (int, int) { 171 // amd64:"SHLQ\t[$]5",-"IMULQ" 172 // 386:"SHLL\t[$]5",-"IMULL" 173 // arm:"SLL\t[$]5",-"MUL" 174 // arm64:"LSL\t[$]5",-"MUL" 175 // ppc64x:"SLD\t[$]5",-"MUL" 176 a := n1 * 32 177 178 // amd64:"SHLQ\t[$]6",-"IMULQ" 179 // 386:"SHLL\t[$]6",-"IMULL" 180 // arm:"SLL\t[$]6",-"MUL" 181 // arm64:`NEG\sR[0-9]+<<6,\sR[0-9]+`,-`LSL`,-`MUL` 182 // ppc64x:"SLD\t[$]6","NEG\\sR[0-9]+,\\sR[0-9]+",-"MUL" 183 b := -64 * n2 184 185 return a, b 186 } 187 188 func Mul_96(n int) int { 189 // amd64:`SHLQ\t[$]5`,`LEAQ\t\(.*\)\(.*\*2\),`,-`IMULQ` 190 // 386:`SHLL\t[$]5`,`LEAL\t\(.*\)\(.*\*2\),`,-`IMULL` 191 // arm64:`LSL\t[$]5`,`ADD\sR[0-9]+<<1,\sR[0-9]+`,-`MUL` 192 // arm:`SLL\t[$]5`,`ADD\sR[0-9]+<<1,\sR[0-9]+`,-`MUL` 193 // s390x:`SLD\t[$]5`,`SLD\t[$]6`,-`MULLD` 194 return n * 96 195 } 196 197 func Mul_n120(n int) int { 198 // s390x:`SLD\t[$]3`,`SLD\t[$]7`,-`MULLD` 199 return n * -120 200 } 201 202 func MulMemSrc(a []uint32, b []float32) { 203 // 386:`IMULL\s4\([A-Z]+\),\s[A-Z]+` 204 a[0] *= a[1] 205 // 386/sse2:`MULSS\s4\([A-Z]+\),\sX[0-9]+` 206 // amd64:`MULSS\s4\([A-Z]+\),\sX[0-9]+` 207 b[0] *= b[1] 208 } 209 210 // Multiplications merging tests 211 212 func MergeMuls1(n int) int { 213 // amd64:"IMUL3Q\t[$]46" 214 // 386:"IMUL3L\t[$]46" 215 // ppc64x:"MULLD\t[$]46" 216 return 15*n + 31*n // 46n 217 } 218 219 func MergeMuls2(n int) int { 220 // amd64:"IMUL3Q\t[$]23","(ADDQ\t[$]29)|(LEAQ\t29)" 221 // 386:"IMUL3L\t[$]23","ADDL\t[$]29" 222 // ppc64x/power9:"MADDLD",-"MULLD\t[$]23",-"ADD\t[$]29" 223 // ppc64x/power8:"MULLD\t[$]23","ADD\t[$]29" 224 return 5*n + 7*(n+1) + 11*(n+2) // 23n + 29 225 } 226 227 func MergeMuls3(a, n int) int { 228 // amd64:"ADDQ\t[$]19",-"IMULQ\t[$]19" 229 // 386:"ADDL\t[$]19",-"IMULL\t[$]19" 230 // ppc64x:"ADD\t[$]19",-"MULLD\t[$]19" 231 return a*n + 19*n // (a+19)n 232 } 233 234 func MergeMuls4(n int) int { 235 // amd64:"IMUL3Q\t[$]14" 236 // 386:"IMUL3L\t[$]14" 237 // ppc64x:"MULLD\t[$]14" 238 return 23*n - 9*n // 14n 239 } 240 241 func MergeMuls5(a, n int) int { 242 // amd64:"ADDQ\t[$]-19",-"IMULQ\t[$]19" 243 // 386:"ADDL\t[$]-19",-"IMULL\t[$]19" 244 // ppc64x:"ADD\t[$]-19",-"MULLD\t[$]19" 245 return a*n - 19*n // (a-19)n 246 } 247 248 // -------------- // 249 // Division // 250 // -------------- // 251 252 func DivMemSrc(a []float64) { 253 // 386/sse2:`DIVSD\s8\([A-Z]+\),\sX[0-9]+` 254 // amd64:`DIVSD\s8\([A-Z]+\),\sX[0-9]+` 255 a[0] /= a[1] 256 } 257 258 func Pow2Divs(n1 uint, n2 int) (uint, int) { 259 // 386:"SHRL\t[$]5",-"DIVL" 260 // amd64:"SHRQ\t[$]5",-"DIVQ" 261 // arm:"SRL\t[$]5",-".*udiv" 262 // arm64:"LSR\t[$]5",-"UDIV" 263 // ppc64x:"SRD" 264 a := n1 / 32 // unsigned 265 266 // amd64:"SARQ\t[$]6",-"IDIVQ" 267 // 386:"SARL\t[$]6",-"IDIVL" 268 // arm:"SRA\t[$]6",-".*udiv" 269 // arm64:"ASR\t[$]6",-"SDIV" 270 // ppc64x:"SRAD" 271 b := n2 / 64 // signed 272 273 return a, b 274 } 275 276 // Check that constant divisions get turned into MULs 277 func ConstDivs(n1 uint, n2 int) (uint, int) { 278 // amd64:"MOVQ\t[$]-1085102592571150095","MULQ",-"DIVQ" 279 // 386:"MOVL\t[$]-252645135","MULL",-"DIVL" 280 // arm64:`MOVD`,`UMULH`,-`DIV` 281 // arm:`MOVW`,`MUL`,-`.*udiv` 282 a := n1 / 17 // unsigned 283 284 // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ" 285 // 386:"MOVL\t[$]-252645135","IMULL",-"IDIVL" 286 // arm64:`SMULH`,-`DIV` 287 // arm:`MOVW`,`MUL`,-`.*udiv` 288 b := n2 / 17 // signed 289 290 return a, b 291 } 292 293 func FloatDivs(a []float32) float32 { 294 // amd64:`DIVSS\s8\([A-Z]+\),\sX[0-9]+` 295 // 386/sse2:`DIVSS\s8\([A-Z]+\),\sX[0-9]+` 296 return a[1] / a[2] 297 } 298 299 func Pow2Mods(n1 uint, n2 int) (uint, int) { 300 // 386:"ANDL\t[$]31",-"DIVL" 301 // amd64:"ANDL\t[$]31",-"DIVQ" 302 // arm:"AND\t[$]31",-".*udiv" 303 // arm64:"AND\t[$]31",-"UDIV" 304 // ppc64x:"RLDICL" 305 a := n1 % 32 // unsigned 306 307 // 386:"SHRL",-"IDIVL" 308 // amd64:"SHRQ",-"IDIVQ" 309 // arm:"SRA",-".*udiv" 310 // arm64:"ASR",-"REM" 311 // ppc64x:"SRAD" 312 b := n2 % 64 // signed 313 314 return a, b 315 } 316 317 // Check that signed divisibility checks get converted to AND on low bits 318 func Pow2DivisibleSigned(n1, n2 int) (bool, bool) { 319 // 386:"TESTL\t[$]63",-"DIVL",-"SHRL" 320 // amd64:"TESTQ\t[$]63",-"DIVQ",-"SHRQ" 321 // arm:"AND\t[$]63",-".*udiv",-"SRA" 322 // arm64:"TST\t[$]63",-"UDIV",-"ASR",-"AND" 323 // ppc64x:"ANDCC",-"RLDICL",-"SRAD",-"CMP" 324 a := n1%64 == 0 // signed divisible 325 326 // 386:"TESTL\t[$]63",-"DIVL",-"SHRL" 327 // amd64:"TESTQ\t[$]63",-"DIVQ",-"SHRQ" 328 // arm:"AND\t[$]63",-".*udiv",-"SRA" 329 // arm64:"TST\t[$]63",-"UDIV",-"ASR",-"AND" 330 // ppc64x:"ANDCC",-"RLDICL",-"SRAD",-"CMP" 331 b := n2%64 != 0 // signed indivisible 332 333 return a, b 334 } 335 336 // Check that constant modulo divs get turned into MULs 337 func ConstMods(n1 uint, n2 int) (uint, int) { 338 // amd64:"MOVQ\t[$]-1085102592571150095","MULQ",-"DIVQ" 339 // 386:"MOVL\t[$]-252645135","MULL",-"DIVL" 340 // arm64:`MOVD`,`UMULH`,-`DIV` 341 // arm:`MOVW`,`MUL`,-`.*udiv` 342 a := n1 % 17 // unsigned 343 344 // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ" 345 // 386:"MOVL\t[$]-252645135","IMULL",-"IDIVL" 346 // arm64:`SMULH`,-`DIV` 347 // arm:`MOVW`,`MUL`,-`.*udiv` 348 b := n2 % 17 // signed 349 350 return a, b 351 } 352 353 // Check that divisibility checks x%c==0 are converted to MULs and rotates 354 func DivisibleU(n uint) (bool, bool) { 355 // amd64:"MOVQ\t[$]-6148914691236517205","IMULQ","ROLQ\t[$]63",-"DIVQ" 356 // 386:"IMUL3L\t[$]-1431655765","ROLL\t[$]31",-"DIVQ" 357 // arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ROR",-"DIV" 358 // arm:"MUL","CMP\t[$]715827882",-".*udiv" 359 // ppc64x:"MULLD","ROTL\t[$]63" 360 even := n%6 == 0 361 362 // amd64:"MOVQ\t[$]-8737931403336103397","IMULQ",-"ROLQ",-"DIVQ" 363 // 386:"IMUL3L\t[$]678152731",-"ROLL",-"DIVQ" 364 // arm64:"MOVD\t[$]-8737931403336103397","MUL",-"ROR",-"DIV" 365 // arm:"MUL","CMP\t[$]226050910",-".*udiv" 366 // ppc64x:"MULLD",-"ROTL" 367 odd := n%19 == 0 368 369 return even, odd 370 } 371 372 func Divisible(n int) (bool, bool) { 373 // amd64:"IMULQ","ADD","ROLQ\t[$]63",-"DIVQ" 374 // 386:"IMUL3L\t[$]-1431655765","ADDL\t[$]715827882","ROLL\t[$]31",-"DIVQ" 375 // arm64:"MOVD\t[$]-6148914691236517205","MOVD\t[$]3074457345618258602","MUL","ADD\tR","ROR",-"DIV" 376 // arm:"MUL","ADD\t[$]715827882",-".*udiv" 377 // ppc64x/power8:"MULLD","ADD","ROTL\t[$]63" 378 // ppc64x/power9:"MADDLD","ROTL\t[$]63" 379 even := n%6 == 0 380 381 // amd64:"IMULQ","ADD",-"ROLQ",-"DIVQ" 382 // 386:"IMUL3L\t[$]678152731","ADDL\t[$]113025455",-"ROLL",-"DIVQ" 383 // arm64:"MUL","MOVD\t[$]485440633518672410","ADD",-"ROR",-"DIV" 384 // arm:"MUL","ADD\t[$]113025455",-".*udiv" 385 // ppc64x/power8:"MULLD","ADD",-"ROTL" 386 // ppc64x/power9:"MADDLD",-"ROTL" 387 odd := n%19 == 0 388 389 return even, odd 390 } 391 392 // Check that fix-up code is not generated for divisions where it has been proven that 393 // that the divisor is not -1 or that the dividend is > MinIntNN. 394 func NoFix64A(divr int64) (int64, int64) { 395 var d int64 = 42 396 var e int64 = 84 397 if divr > 5 { 398 d /= divr // amd64:-"JMP" 399 e %= divr // amd64:-"JMP" 400 // The following statement is to avoid conflict between the above check 401 // and the normal JMP generated at the end of the block. 402 d += e 403 } 404 return d, e 405 } 406 407 func NoFix64B(divd int64) (int64, int64) { 408 var d int64 409 var e int64 410 var divr int64 = -1 411 if divd > -9223372036854775808 { 412 d = divd / divr // amd64:-"JMP" 413 e = divd % divr // amd64:-"JMP" 414 d += e 415 } 416 return d, e 417 } 418 419 func NoFix32A(divr int32) (int32, int32) { 420 var d int32 = 42 421 var e int32 = 84 422 if divr > 5 { 423 // amd64:-"JMP" 424 // 386:-"JMP" 425 d /= divr 426 // amd64:-"JMP" 427 // 386:-"JMP" 428 e %= divr 429 d += e 430 } 431 return d, e 432 } 433 434 func NoFix32B(divd int32) (int32, int32) { 435 var d int32 436 var e int32 437 var divr int32 = -1 438 if divd > -2147483648 { 439 // amd64:-"JMP" 440 // 386:-"JMP" 441 d = divd / divr 442 // amd64:-"JMP" 443 // 386:-"JMP" 444 e = divd % divr 445 d += e 446 } 447 return d, e 448 } 449 450 func NoFix16A(divr int16) (int16, int16) { 451 var d int16 = 42 452 var e int16 = 84 453 if divr > 5 { 454 // amd64:-"JMP" 455 // 386:-"JMP" 456 d /= divr 457 // amd64:-"JMP" 458 // 386:-"JMP" 459 e %= divr 460 d += e 461 } 462 return d, e 463 } 464 465 func NoFix16B(divd int16) (int16, int16) { 466 var d int16 467 var e int16 468 var divr int16 = -1 469 if divd > -32768 { 470 // amd64:-"JMP" 471 // 386:-"JMP" 472 d = divd / divr 473 // amd64:-"JMP" 474 // 386:-"JMP" 475 e = divd % divr 476 d += e 477 } 478 return d, e 479 } 480 481 // Check that len() and cap() calls divided by powers of two are 482 // optimized into shifts and ands 483 484 func LenDiv1(a []int) int { 485 // 386:"SHRL\t[$]10" 486 // amd64:"SHRQ\t[$]10" 487 // arm64:"LSR\t[$]10",-"SDIV" 488 // arm:"SRL\t[$]10",-".*udiv" 489 // ppc64x:"SRD"\t[$]10" 490 return len(a) / 1024 491 } 492 493 func LenDiv2(s string) int { 494 // 386:"SHRL\t[$]11" 495 // amd64:"SHRQ\t[$]11" 496 // arm64:"LSR\t[$]11",-"SDIV" 497 // arm:"SRL\t[$]11",-".*udiv" 498 // ppc64x:"SRD\t[$]11" 499 return len(s) / (4097 >> 1) 500 } 501 502 func LenMod1(a []int) int { 503 // 386:"ANDL\t[$]1023" 504 // amd64:"ANDL\t[$]1023" 505 // arm64:"AND\t[$]1023",-"SDIV" 506 // arm/6:"AND",-".*udiv" 507 // arm/7:"BFC",-".*udiv",-"AND" 508 // ppc64x:"RLDICL" 509 return len(a) % 1024 510 } 511 512 func LenMod2(s string) int { 513 // 386:"ANDL\t[$]2047" 514 // amd64:"ANDL\t[$]2047" 515 // arm64:"AND\t[$]2047",-"SDIV" 516 // arm/6:"AND",-".*udiv" 517 // arm/7:"BFC",-".*udiv",-"AND" 518 // ppc64x:"RLDICL" 519 return len(s) % (4097 >> 1) 520 } 521 522 func CapDiv(a []int) int { 523 // 386:"SHRL\t[$]12" 524 // amd64:"SHRQ\t[$]12" 525 // arm64:"LSR\t[$]12",-"SDIV" 526 // arm:"SRL\t[$]12",-".*udiv" 527 // ppc64x:"SRD\t[$]12" 528 return cap(a) / ((1 << 11) + 2048) 529 } 530 531 func CapMod(a []int) int { 532 // 386:"ANDL\t[$]4095" 533 // amd64:"ANDL\t[$]4095" 534 // arm64:"AND\t[$]4095",-"SDIV" 535 // arm/6:"AND",-".*udiv" 536 // arm/7:"BFC",-".*udiv",-"AND" 537 // ppc64x:"RLDICL" 538 return cap(a) % ((1 << 11) + 2048) 539 } 540 541 func AddMul(x int) int { 542 // amd64:"LEAQ\t1" 543 return 2*x + 1 544 } 545 546 func MULA(a, b, c uint32) (uint32, uint32, uint32) { 547 // arm:`MULA`,-`MUL\s` 548 // arm64:`MADDW`,-`MULW` 549 r0 := a*b + c 550 // arm:`MULA`,-`MUL\s` 551 // arm64:`MADDW`,-`MULW` 552 r1 := c*79 + a 553 // arm:`ADD`,-`MULA`,-`MUL\s` 554 // arm64:`ADD`,-`MADD`,-`MULW` 555 // ppc64x:`ADD`,-`MULLD` 556 r2 := b*64 + c 557 return r0, r1, r2 558 } 559 560 func MULS(a, b, c uint32) (uint32, uint32, uint32) { 561 // arm/7:`MULS`,-`MUL\s` 562 // arm/6:`SUB`,`MUL\s`,-`MULS` 563 // arm64:`MSUBW`,-`MULW` 564 r0 := c - a*b 565 // arm/7:`MULS`,-`MUL\s` 566 // arm/6:`SUB`,`MUL\s`,-`MULS` 567 // arm64:`MSUBW`,-`MULW` 568 r1 := a - c*79 569 // arm/7:`SUB`,-`MULS`,-`MUL\s` 570 // arm64:`SUB`,-`MSUBW`,-`MULW` 571 // ppc64x:`SUB`,-`MULLD` 572 r2 := c - b*64 573 return r0, r1, r2 574 } 575 576 func addSpecial(a, b, c uint32) (uint32, uint32, uint32) { 577 // amd64:`INCL` 578 a++ 579 // amd64:`DECL` 580 b-- 581 // amd64:`SUBL.*-128` 582 c += 128 583 return a, b, c 584 } 585 586 // Divide -> shift rules usually require fixup for negative inputs. 587 // If the input is non-negative, make sure the fixup is eliminated. 588 func divInt(v int64) int64 { 589 if v < 0 { 590 return 0 591 } 592 // amd64:-`.*SARQ.*63,`, -".*SHRQ", ".*SARQ.*[$]9," 593 return v / 512 594 } 595 596 // The reassociate rules "x - (z + C) -> (x - z) - C" and 597 // "(z + C) -x -> C + (z - x)" can optimize the following cases. 598 func constantFold1(i0, j0, i1, j1, i2, j2, i3, j3 int) (int, int, int, int) { 599 // arm64:"SUB","ADD\t[$]2" 600 // ppc64x:"SUB","ADD\t[$]2" 601 r0 := (i0 + 3) - (j0 + 1) 602 // arm64:"SUB","SUB\t[$]4" 603 // ppc64x:"SUB","ADD\t[$]-4" 604 r1 := (i1 - 3) - (j1 + 1) 605 // arm64:"SUB","ADD\t[$]4" 606 // ppc64x:"SUB","ADD\t[$]4" 607 r2 := (i2 + 3) - (j2 - 1) 608 // arm64:"SUB","SUB\t[$]2" 609 // ppc64x:"SUB","ADD\t[$]-2" 610 r3 := (i3 - 3) - (j3 - 1) 611 return r0, r1, r2, r3 612 } 613 614 // The reassociate rules "x - (z + C) -> (x - z) - C" and 615 // "(C - z) - x -> C - (z + x)" can optimize the following cases. 616 func constantFold2(i0, j0, i1, j1 int) (int, int) { 617 // arm64:"ADD","MOVD\t[$]2","SUB" 618 // ppc64x: `SUBC\tR[0-9]+,\s[$]2,\sR` 619 r0 := (3 - i0) - (j0 + 1) 620 // arm64:"ADD","MOVD\t[$]4","SUB" 621 // ppc64x: `SUBC\tR[0-9]+,\s[$]4,\sR` 622 r1 := (3 - i1) - (j1 - 1) 623 return r0, r1 624 } 625 626 func constantFold3(i, j int) int { 627 // arm64: "MOVD\t[$]30","MUL",-"ADD",-"LSL" 628 // ppc64x:"MULLD\t[$]30","MULLD" 629 r := (5 * i) * (6 * j) 630 return r 631 } 632