github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/src/cmd/compile/internal/ssa/magic.go (about)

     1  // Copyright 2016 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssa
     6  
     7  import "math/big"
     8  
     9  // So you want to compute x / c for some constant c?
    10  // Machine division instructions are slow, so we try to
    11  // compute this division with a multiplication + a few
    12  // other cheap instructions instead.
    13  // (We assume here that c != 0, +/- 1, or +/- 2^i.  Those
    14  // cases are easy to handle in different ways).
    15  
    16  // Technique from https://gmplib.org/~tege/divcnst-pldi94.pdf
    17  
    18  // First consider unsigned division.
    19  // Our strategy is to precompute 1/c then do
    20  //   ⎣x / c⎦ = ⎣x * (1/c)⎦.
    21  // 1/c is less than 1, so we can't compute it directly in
    22  // integer arithmetic.  Let's instead compute 2^e/c
    23  // for a value of e TBD (^ = exponentiation).  Then
    24  //   ⎣x / c⎦ = ⎣x * (2^e/c) / 2^e⎦.
    25  // Dividing by 2^e is easy.  2^e/c isn't an integer, unfortunately.
    26  // So we must approximate it.  Let's call its approximation m.
    27  // We'll then compute
    28  //   ⎣x * m / 2^e⎦
    29  // Which we want to be equal to ⎣x / c⎦ for 0 <= x < 2^n-1
    30  // where n is the word size.
    31  // Setting x = c gives us c * m >= 2^e.
    32  // We'll chose m = ⎡2^e/c⎤ to satisfy that equation.
    33  // What remains is to choose e.
    34  // Let m = 2^e/c + delta, 0 <= delta < 1
    35  //   ⎣x * (2^e/c + delta) / 2^e⎦
    36  //   ⎣x / c + x * delta / 2^e⎦
    37  // We must have x * delta / 2^e < 1/c so that this
    38  // additional term never rounds differently than ⎣x / c⎦ does.
    39  // Rearranging,
    40  //   2^e > x * delta * c
    41  // x can be at most 2^n-1 and delta can be at most 1.
    42  // So it is sufficient to have 2^e >= 2^n*c.
    43  // So we'll choose e = n + s, with s = ⎡log2(c)⎤.
    44  //
    45  // An additional complication arises because m has n+1 bits in it.
    46  // Hardware restricts us to n bit by n bit multiplies.
    47  // We divide into 3 cases:
    48  //
    49  // Case 1: m is even.
    50  //   ⎣x / c⎦ = ⎣x * m / 2^(n+s)⎦
    51  //   ⎣x / c⎦ = ⎣x * (m/2) / 2^(n+s-1)⎦
    52  //   ⎣x / c⎦ = ⎣x * (m/2) / 2^n / 2^(s-1)⎦
    53  //   ⎣x / c⎦ = ⎣⎣x * (m/2) / 2^n⎦ / 2^(s-1)⎦
    54  //   multiply + shift
    55  //
    56  // Case 2: c is even.
    57  //   ⎣x / c⎦ = ⎣(x/2) / (c/2)⎦
    58  //   ⎣x / c⎦ = ⎣⎣x/2⎦ / (c/2)⎦
    59  //     This is just the original problem, with x' = ⎣x/2⎦, c' = c/2, n' = n-1.
    60  //       s' = s-1
    61  //       m' = ⎡2^(n'+s')/c'⎤
    62  //          = ⎡2^(n+s-1)/c⎤
    63  //          = ⎡m/2⎤
    64  //   ⎣x / c⎦ = ⎣x' * m' / 2^(n'+s')⎦
    65  //   ⎣x / c⎦ = ⎣⎣x/2⎦ * ⎡m/2⎤ / 2^(n+s-2)⎦
    66  //   ⎣x / c⎦ = ⎣⎣⎣x/2⎦ * ⎡m/2⎤ / 2^n⎦ / 2^(s-2)⎦
    67  //   shift + multiply + shift
    68  //
    69  // Case 3: everything else
    70  //   let k = m - 2^n. k fits in n bits.
    71  //   ⎣x / c⎦ = ⎣x * m / 2^(n+s)⎦
    72  //   ⎣x / c⎦ = ⎣x * (2^n + k) / 2^(n+s)⎦
    73  //   ⎣x / c⎦ = ⎣(x + x * k / 2^n) / 2^s⎦
    74  //   ⎣x / c⎦ = ⎣(x + ⎣x * k / 2^n⎦) / 2^s⎦
    75  //   ⎣x / c⎦ = ⎣(x + ⎣x * k / 2^n⎦) / 2^s⎦
    76  //   ⎣x / c⎦ = ⎣⎣(x + ⎣x * k / 2^n⎦) / 2⎦ / 2^(s-1)⎦
    77  //   multiply + avg + shift
    78  //
    79  // These can be implemented in hardware using:
    80  //  ⎣a * b / 2^n⎦ - aka high n bits of an n-bit by n-bit multiply.
    81  //  ⎣(a+b) / 2⎦   - aka "average" of two n-bit numbers.
    82  //                  (Not just a regular add & shift because the intermediate result
    83  //                   a+b has n+1 bits in it.  Nevertheless, can be done
    84  //                   in 2 instructions on x86.)
    85  
    86  // umagicOK returns whether we should strength reduce a n-bit divide by c.
    87  func umagicOK(n uint, c int64) bool {
    88  	// Convert from ConstX auxint values to the real uint64 constant they represent.
    89  	d := uint64(c) << (64 - n) >> (64 - n)
    90  
    91  	// Doesn't work for 0.
    92  	// Don't use for powers of 2.
    93  	return d&(d-1) != 0
    94  }
    95  
    96  type umagicData struct {
    97  	s int64  // ⎡log2(c)⎤
    98  	m uint64 // ⎡2^(n+s)/c⎤ - 2^n
    99  }
   100  
   101  // umagic computes the constants needed to strength reduce unsigned n-bit divides by the constant uint64(c).
   102  // The return values satisfy for all 0 <= x < 2^n
   103  //  floor(x / uint64(c)) = x * (m + 2^n) >> (n+s)
   104  func umagic(n uint, c int64) umagicData {
   105  	// Convert from ConstX auxint values to the real uint64 constant they represent.
   106  	d := uint64(c) << (64 - n) >> (64 - n)
   107  
   108  	C := new(big.Int).SetUint64(d)
   109  	s := C.BitLen()
   110  	M := big.NewInt(1)
   111  	M.Lsh(M, n+uint(s))     // 2^(n+s)
   112  	M.Add(M, C)             // 2^(n+s)+c
   113  	M.Sub(M, big.NewInt(1)) // 2^(n+s)+c-1
   114  	M.Div(M, C)             // ⎡2^(n+s)/c⎤
   115  	if M.Bit(int(n)) != 1 {
   116  		panic("n+1st bit isn't set")
   117  	}
   118  	M.SetBit(M, int(n), 0)
   119  	m := M.Uint64()
   120  	return umagicData{s: int64(s), m: m}
   121  }
   122  
   123  // For signed division, we use a similar strategy.
   124  // First, we enforce a positive c.
   125  //   x / c = -(x / (-c))
   126  // This will require an additional Neg op for c<0.
   127  //
   128  // If x is positive we're in a very similar state
   129  // to the unsigned case above.  We define:
   130  //   s = ⎡log2(c)⎤-1
   131  //   m = ⎡2^(n+s)/c⎤
   132  // Then
   133  //   ⎣x / c⎦ = ⎣x * m / 2^(n+s)⎦
   134  // If x is negative we have
   135  //   ⎡x / c⎤ = ⎣x * m / 2^(n+s)⎦ + 1
   136  // (TODO: derivation?)
   137  //
   138  // The multiply is a bit odd, as it is a signed n-bit value
   139  // times an unsigned n-bit value.  For n smaller than the
   140  // word size, we can extend x and m appropriately and use the
   141  // signed multiply instruction.  For n == word size,
   142  // we must use the signed multiply high and correct
   143  // the result by adding x*2^n.
   144  //
   145  // Adding 1 if x<0 is done by subtracting x>>(n-1).
   146  
   147  func smagicOK(n uint, c int64) bool {
   148  	if c < 0 {
   149  		// Doesn't work for negative c.
   150  		return false
   151  	}
   152  	// Doesn't work for 0.
   153  	// Don't use it for powers of 2.
   154  	return c&(c-1) != 0
   155  }
   156  
   157  type smagicData struct {
   158  	s int64  // ⎡log2(c)⎤-1
   159  	m uint64 // ⎡2^(n+s)/c⎤
   160  }
   161  
   162  // magic computes the constants needed to strength reduce signed n-bit divides by the constant c.
   163  // Must have c>0.
   164  // The return values satisfy for all -2^(n-1) <= x < 2^(n-1)
   165  //  trunc(x / c) = x * m >> (n+s) + (x < 0 ? 1 : 0)
   166  func smagic(n uint, c int64) smagicData {
   167  	C := new(big.Int).SetInt64(c)
   168  	s := C.BitLen() - 1
   169  	M := big.NewInt(1)
   170  	M.Lsh(M, n+uint(s))     // 2^(n+s)
   171  	M.Add(M, C)             // 2^(n+s)+c
   172  	M.Sub(M, big.NewInt(1)) // 2^(n+s)+c-1
   173  	M.Div(M, C)             // ⎡2^(n+s)/c⎤
   174  	if M.Bit(int(n)) != 0 {
   175  		panic("n+1st bit is set")
   176  	}
   177  	if M.Bit(int(n-1)) == 0 {
   178  		panic("nth bit is not set")
   179  	}
   180  	m := M.Uint64()
   181  	return smagicData{s: int64(s), m: m}
   182  }