github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/src/cmd/compile/internal/gc/magic.go (about) 1 // Copyright 2009 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 gc 6 7 // Transmogrify slow integer division into fast multiplication using magic. 8 9 // argument passing to/from 10 // smagic and umagic 11 type Magic struct { 12 W int // input for both - width 13 S int // output for both - shift 14 Bad int // output for both - unexpected failure 15 16 // magic multiplier for signed literal divisors 17 Sd int64 // input - literal divisor 18 Sm int64 // output - multiplier 19 20 // magic multiplier for unsigned literal divisors 21 Ud uint64 // input - literal divisor 22 Um uint64 // output - multiplier 23 Ua int // output - adder 24 } 25 26 // magic number for signed division 27 // see hacker's delight chapter 10 28 func smagic(m *Magic) { 29 var mask uint64 30 31 m.Bad = 0 32 switch m.W { 33 default: 34 m.Bad = 1 35 return 36 37 case 8: 38 mask = 0xff 39 40 case 16: 41 mask = 0xffff 42 43 case 32: 44 mask = 0xffffffff 45 46 case 64: 47 mask = 0xffffffffffffffff 48 } 49 50 two31 := mask ^ (mask >> 1) 51 52 p := m.W - 1 53 ad := uint64(m.Sd) 54 if m.Sd < 0 { 55 ad = -uint64(m.Sd) 56 } 57 58 // bad denominators 59 if ad == 0 || ad == 1 || ad == two31 { 60 m.Bad = 1 61 return 62 } 63 64 t := two31 65 ad &= mask 66 67 anc := t - 1 - t%ad 68 anc &= mask 69 70 q1 := two31 / anc 71 r1 := two31 - q1*anc 72 q1 &= mask 73 r1 &= mask 74 75 q2 := two31 / ad 76 r2 := two31 - q2*ad 77 q2 &= mask 78 r2 &= mask 79 80 var delta uint64 81 for { 82 p++ 83 q1 <<= 1 84 r1 <<= 1 85 q1 &= mask 86 r1 &= mask 87 if r1 >= anc { 88 q1++ 89 r1 -= anc 90 q1 &= mask 91 r1 &= mask 92 } 93 94 q2 <<= 1 95 r2 <<= 1 96 q2 &= mask 97 r2 &= mask 98 if r2 >= ad { 99 q2++ 100 r2 -= ad 101 q2 &= mask 102 r2 &= mask 103 } 104 105 delta = ad - r2 106 delta &= mask 107 if q1 < delta || (q1 == delta && r1 == 0) { 108 continue 109 } 110 111 break 112 } 113 114 m.Sm = int64(q2 + 1) 115 if uint64(m.Sm)&two31 != 0 { 116 m.Sm |= ^int64(mask) 117 } 118 m.S = p - m.W 119 } 120 121 // magic number for unsigned division 122 // see hacker's delight chapter 10 123 func umagic(m *Magic) { 124 var mask uint64 125 126 m.Bad = 0 127 m.Ua = 0 128 129 switch m.W { 130 default: 131 m.Bad = 1 132 return 133 134 case 8: 135 mask = 0xff 136 137 case 16: 138 mask = 0xffff 139 140 case 32: 141 mask = 0xffffffff 142 143 case 64: 144 mask = 0xffffffffffffffff 145 } 146 147 two31 := mask ^ (mask >> 1) 148 149 m.Ud &= mask 150 if m.Ud == 0 || m.Ud == two31 { 151 m.Bad = 1 152 return 153 } 154 155 nc := mask - (-m.Ud&mask)%m.Ud 156 p := m.W - 1 157 158 q1 := two31 / nc 159 r1 := two31 - q1*nc 160 q1 &= mask 161 r1 &= mask 162 163 q2 := (two31 - 1) / m.Ud 164 r2 := (two31 - 1) - q2*m.Ud 165 q2 &= mask 166 r2 &= mask 167 168 var delta uint64 169 for { 170 p++ 171 if r1 >= nc-r1 { 172 q1 <<= 1 173 q1++ 174 r1 <<= 1 175 r1 -= nc 176 } else { 177 q1 <<= 1 178 r1 <<= 1 179 } 180 181 q1 &= mask 182 r1 &= mask 183 if r2+1 >= m.Ud-r2 { 184 if q2 >= two31-1 { 185 m.Ua = 1 186 } 187 188 q2 <<= 1 189 q2++ 190 r2 <<= 1 191 r2++ 192 r2 -= m.Ud 193 } else { 194 if q2 >= two31 { 195 m.Ua = 1 196 } 197 198 q2 <<= 1 199 r2 <<= 1 200 r2++ 201 } 202 203 q2 &= mask 204 r2 &= mask 205 206 delta = m.Ud - 1 - r2 207 delta &= mask 208 209 if p < m.W+m.W { 210 if q1 < delta || (q1 == delta && r1 == 0) { 211 continue 212 } 213 } 214 215 break 216 } 217 218 m.Um = q2 + 1 219 m.S = p - m.W 220 }