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:"RLDICL",-"SRAD"
   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:"RLDICL",-"SRAD"
   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  

View as plain text