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