github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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  // A copy of the code in ../gc/subr.go.
     8  // We can't use it directly because it would generate
     9  // an import cycle. TODO: move to a common support package.
    10  
    11  // argument passing to/from
    12  // smagic and umagic
    13  type magic struct {
    14  	W   int // input for both - width
    15  	S   int // output for both - shift
    16  	Bad int // output for both - unexpected failure
    17  
    18  	// magic multiplier for signed literal divisors
    19  	Sd int64 // input - literal divisor
    20  	Sm int64 // output - multiplier
    21  
    22  	// magic multiplier for unsigned literal divisors
    23  	Ud uint64 // input - literal divisor
    24  	Um uint64 // output - multiplier
    25  	Ua int    // output - adder
    26  }
    27  
    28  // magic number for signed division
    29  // see hacker's delight chapter 10
    30  func smagic(m *magic) {
    31  	var mask uint64
    32  
    33  	m.Bad = 0
    34  	switch m.W {
    35  	default:
    36  		m.Bad = 1
    37  		return
    38  
    39  	case 8:
    40  		mask = 0xff
    41  
    42  	case 16:
    43  		mask = 0xffff
    44  
    45  	case 32:
    46  		mask = 0xffffffff
    47  
    48  	case 64:
    49  		mask = 0xffffffffffffffff
    50  	}
    51  
    52  	two31 := mask ^ (mask >> 1)
    53  
    54  	p := m.W - 1
    55  	ad := uint64(m.Sd)
    56  	if m.Sd < 0 {
    57  		ad = -uint64(m.Sd)
    58  	}
    59  
    60  	// bad denominators
    61  	if ad == 0 || ad == 1 || ad == two31 {
    62  		m.Bad = 1
    63  		return
    64  	}
    65  
    66  	t := two31
    67  	ad &= mask
    68  
    69  	anc := t - 1 - t%ad
    70  	anc &= mask
    71  
    72  	q1 := two31 / anc
    73  	r1 := two31 - q1*anc
    74  	q1 &= mask
    75  	r1 &= mask
    76  
    77  	q2 := two31 / ad
    78  	r2 := two31 - q2*ad
    79  	q2 &= mask
    80  	r2 &= mask
    81  
    82  	var delta uint64
    83  	for {
    84  		p++
    85  		q1 <<= 1
    86  		r1 <<= 1
    87  		q1 &= mask
    88  		r1 &= mask
    89  		if r1 >= anc {
    90  			q1++
    91  			r1 -= anc
    92  			q1 &= mask
    93  			r1 &= mask
    94  		}
    95  
    96  		q2 <<= 1
    97  		r2 <<= 1
    98  		q2 &= mask
    99  		r2 &= mask
   100  		if r2 >= ad {
   101  			q2++
   102  			r2 -= ad
   103  			q2 &= mask
   104  			r2 &= mask
   105  		}
   106  
   107  		delta = ad - r2
   108  		delta &= mask
   109  		if q1 < delta || (q1 == delta && r1 == 0) {
   110  			continue
   111  		}
   112  
   113  		break
   114  	}
   115  
   116  	m.Sm = int64(q2 + 1)
   117  	if uint64(m.Sm)&two31 != 0 {
   118  		m.Sm |= ^int64(mask)
   119  	}
   120  	m.S = p - m.W
   121  }
   122  
   123  // magic number for unsigned division
   124  // see hacker's delight chapter 10
   125  func umagic(m *magic) {
   126  	var mask uint64
   127  
   128  	m.Bad = 0
   129  	m.Ua = 0
   130  
   131  	switch m.W {
   132  	default:
   133  		m.Bad = 1
   134  		return
   135  
   136  	case 8:
   137  		mask = 0xff
   138  
   139  	case 16:
   140  		mask = 0xffff
   141  
   142  	case 32:
   143  		mask = 0xffffffff
   144  
   145  	case 64:
   146  		mask = 0xffffffffffffffff
   147  	}
   148  
   149  	two31 := mask ^ (mask >> 1)
   150  
   151  	m.Ud &= mask
   152  	if m.Ud == 0 || m.Ud == two31 {
   153  		m.Bad = 1
   154  		return
   155  	}
   156  
   157  	nc := mask - (-m.Ud&mask)%m.Ud
   158  	p := m.W - 1
   159  
   160  	q1 := two31 / nc
   161  	r1 := two31 - q1*nc
   162  	q1 &= mask
   163  	r1 &= mask
   164  
   165  	q2 := (two31 - 1) / m.Ud
   166  	r2 := (two31 - 1) - q2*m.Ud
   167  	q2 &= mask
   168  	r2 &= mask
   169  
   170  	var delta uint64
   171  	for {
   172  		p++
   173  		if r1 >= nc-r1 {
   174  			q1 <<= 1
   175  			q1++
   176  			r1 <<= 1
   177  			r1 -= nc
   178  		} else {
   179  			q1 <<= 1
   180  			r1 <<= 1
   181  		}
   182  
   183  		q1 &= mask
   184  		r1 &= mask
   185  		if r2+1 >= m.Ud-r2 {
   186  			if q2 >= two31-1 {
   187  				m.Ua = 1
   188  			}
   189  
   190  			q2 <<= 1
   191  			q2++
   192  			r2 <<= 1
   193  			r2++
   194  			r2 -= m.Ud
   195  		} else {
   196  			if q2 >= two31 {
   197  				m.Ua = 1
   198  			}
   199  
   200  			q2 <<= 1
   201  			r2 <<= 1
   202  			r2++
   203  		}
   204  
   205  		q2 &= mask
   206  		r2 &= mask
   207  
   208  		delta = m.Ud - 1 - r2
   209  		delta &= mask
   210  
   211  		if p < m.W+m.W {
   212  			if q1 < delta || (q1 == delta && r1 == 0) {
   213  				continue
   214  			}
   215  		}
   216  
   217  		break
   218  	}
   219  
   220  	m.Um = q2 + 1
   221  	m.S = p - m.W
   222  }
   223  
   224  // adaptors for use by rewrite rules
   225  func smagic64ok(d int64) bool {
   226  	m := magic{W: 64, Sd: d}
   227  	smagic(&m)
   228  	return m.Bad == 0
   229  }
   230  func smagic64m(d int64) int64 {
   231  	m := magic{W: 64, Sd: d}
   232  	smagic(&m)
   233  	return m.Sm
   234  }
   235  func smagic64s(d int64) int64 {
   236  	m := magic{W: 64, Sd: d}
   237  	smagic(&m)
   238  	return int64(m.S)
   239  }
   240  
   241  func umagic64ok(d int64) bool {
   242  	m := magic{W: 64, Ud: uint64(d)}
   243  	umagic(&m)
   244  	return m.Bad == 0
   245  }
   246  func umagic64m(d int64) int64 {
   247  	m := magic{W: 64, Ud: uint64(d)}
   248  	umagic(&m)
   249  	return int64(m.Um)
   250  }
   251  func umagic64s(d int64) int64 {
   252  	m := magic{W: 64, Ud: uint64(d)}
   253  	umagic(&m)
   254  	return int64(m.S)
   255  }
   256  func umagic64a(d int64) bool {
   257  	m := magic{W: 64, Ud: uint64(d)}
   258  	umagic(&m)
   259  	return m.Ua != 0
   260  }