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  

View as plain text