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

View as plain text