Source file src/cmd/compile/internal/test/shift_test.go

     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 test
     6  
     7  import (
     8  	"reflect"
     9  	"testing"
    10  )
    11  
    12  // Tests shifts of zero.
    13  
    14  //go:noinline
    15  func ofz64l64(n uint64) int64 {
    16  	var x int64
    17  	return x << n
    18  }
    19  
    20  //go:noinline
    21  func ofz64l32(n uint32) int64 {
    22  	var x int64
    23  	return x << n
    24  }
    25  
    26  //go:noinline
    27  func ofz64l16(n uint16) int64 {
    28  	var x int64
    29  	return x << n
    30  }
    31  
    32  //go:noinline
    33  func ofz64l8(n uint8) int64 {
    34  	var x int64
    35  	return x << n
    36  }
    37  
    38  //go:noinline
    39  func ofz64r64(n uint64) int64 {
    40  	var x int64
    41  	return x >> n
    42  }
    43  
    44  //go:noinline
    45  func ofz64r32(n uint32) int64 {
    46  	var x int64
    47  	return x >> n
    48  }
    49  
    50  //go:noinline
    51  func ofz64r16(n uint16) int64 {
    52  	var x int64
    53  	return x >> n
    54  }
    55  
    56  //go:noinline
    57  func ofz64r8(n uint8) int64 {
    58  	var x int64
    59  	return x >> n
    60  }
    61  
    62  //go:noinline
    63  func ofz64ur64(n uint64) uint64 {
    64  	var x uint64
    65  	return x >> n
    66  }
    67  
    68  //go:noinline
    69  func ofz64ur32(n uint32) uint64 {
    70  	var x uint64
    71  	return x >> n
    72  }
    73  
    74  //go:noinline
    75  func ofz64ur16(n uint16) uint64 {
    76  	var x uint64
    77  	return x >> n
    78  }
    79  
    80  //go:noinline
    81  func ofz64ur8(n uint8) uint64 {
    82  	var x uint64
    83  	return x >> n
    84  }
    85  
    86  //go:noinline
    87  func ofz32l64(n uint64) int32 {
    88  	var x int32
    89  	return x << n
    90  }
    91  
    92  //go:noinline
    93  func ofz32l32(n uint32) int32 {
    94  	var x int32
    95  	return x << n
    96  }
    97  
    98  //go:noinline
    99  func ofz32l16(n uint16) int32 {
   100  	var x int32
   101  	return x << n
   102  }
   103  
   104  //go:noinline
   105  func ofz32l8(n uint8) int32 {
   106  	var x int32
   107  	return x << n
   108  }
   109  
   110  //go:noinline
   111  func ofz32r64(n uint64) int32 {
   112  	var x int32
   113  	return x >> n
   114  }
   115  
   116  //go:noinline
   117  func ofz32r32(n uint32) int32 {
   118  	var x int32
   119  	return x >> n
   120  }
   121  
   122  //go:noinline
   123  func ofz32r16(n uint16) int32 {
   124  	var x int32
   125  	return x >> n
   126  }
   127  
   128  //go:noinline
   129  func ofz32r8(n uint8) int32 {
   130  	var x int32
   131  	return x >> n
   132  }
   133  
   134  //go:noinline
   135  func ofz32ur64(n uint64) uint32 {
   136  	var x uint32
   137  	return x >> n
   138  }
   139  
   140  //go:noinline
   141  func ofz32ur32(n uint32) uint32 {
   142  	var x uint32
   143  	return x >> n
   144  }
   145  
   146  //go:noinline
   147  func ofz32ur16(n uint16) uint32 {
   148  	var x uint32
   149  	return x >> n
   150  }
   151  
   152  //go:noinline
   153  func ofz32ur8(n uint8) uint32 {
   154  	var x uint32
   155  	return x >> n
   156  }
   157  
   158  //go:noinline
   159  func ofz16l64(n uint64) int16 {
   160  	var x int16
   161  	return x << n
   162  }
   163  
   164  //go:noinline
   165  func ofz16l32(n uint32) int16 {
   166  	var x int16
   167  	return x << n
   168  }
   169  
   170  //go:noinline
   171  func ofz16l16(n uint16) int16 {
   172  	var x int16
   173  	return x << n
   174  }
   175  
   176  //go:noinline
   177  func ofz16l8(n uint8) int16 {
   178  	var x int16
   179  	return x << n
   180  }
   181  
   182  //go:noinline
   183  func ofz16r64(n uint64) int16 {
   184  	var x int16
   185  	return x >> n
   186  }
   187  
   188  //go:noinline
   189  func ofz16r32(n uint32) int16 {
   190  	var x int16
   191  	return x >> n
   192  }
   193  
   194  //go:noinline
   195  func ofz16r16(n uint16) int16 {
   196  	var x int16
   197  	return x >> n
   198  }
   199  
   200  //go:noinline
   201  func ofz16r8(n uint8) int16 {
   202  	var x int16
   203  	return x >> n
   204  }
   205  
   206  //go:noinline
   207  func ofz16ur64(n uint64) uint16 {
   208  	var x uint16
   209  	return x >> n
   210  }
   211  
   212  //go:noinline
   213  func ofz16ur32(n uint32) uint16 {
   214  	var x uint16
   215  	return x >> n
   216  }
   217  
   218  //go:noinline
   219  func ofz16ur16(n uint16) uint16 {
   220  	var x uint16
   221  	return x >> n
   222  }
   223  
   224  //go:noinline
   225  func ofz16ur8(n uint8) uint16 {
   226  	var x uint16
   227  	return x >> n
   228  }
   229  
   230  //go:noinline
   231  func ofz8l64(n uint64) int8 {
   232  	var x int8
   233  	return x << n
   234  }
   235  
   236  //go:noinline
   237  func ofz8l32(n uint32) int8 {
   238  	var x int8
   239  	return x << n
   240  }
   241  
   242  //go:noinline
   243  func ofz8l16(n uint16) int8 {
   244  	var x int8
   245  	return x << n
   246  }
   247  
   248  //go:noinline
   249  func ofz8l8(n uint8) int8 {
   250  	var x int8
   251  	return x << n
   252  }
   253  
   254  //go:noinline
   255  func ofz8r64(n uint64) int8 {
   256  	var x int8
   257  	return x >> n
   258  }
   259  
   260  //go:noinline
   261  func ofz8r32(n uint32) int8 {
   262  	var x int8
   263  	return x >> n
   264  }
   265  
   266  //go:noinline
   267  func ofz8r16(n uint16) int8 {
   268  	var x int8
   269  	return x >> n
   270  }
   271  
   272  //go:noinline
   273  func ofz8r8(n uint8) int8 {
   274  	var x int8
   275  	return x >> n
   276  }
   277  
   278  //go:noinline
   279  func ofz8ur64(n uint64) uint8 {
   280  	var x uint8
   281  	return x >> n
   282  }
   283  
   284  //go:noinline
   285  func ofz8ur32(n uint32) uint8 {
   286  	var x uint8
   287  	return x >> n
   288  }
   289  
   290  //go:noinline
   291  func ofz8ur16(n uint16) uint8 {
   292  	var x uint8
   293  	return x >> n
   294  }
   295  
   296  //go:noinline
   297  func ofz8ur8(n uint8) uint8 {
   298  	var x uint8
   299  	return x >> n
   300  }
   301  
   302  func TestShiftOfZero(t *testing.T) {
   303  	if got := ofz64l64(5); got != 0 {
   304  		t.Errorf("0<<5 == %d, want 0", got)
   305  	}
   306  	if got := ofz64l32(5); got != 0 {
   307  		t.Errorf("0<<5 == %d, want 0", got)
   308  	}
   309  	if got := ofz64l16(5); got != 0 {
   310  		t.Errorf("0<<5 == %d, want 0", got)
   311  	}
   312  	if got := ofz64l8(5); got != 0 {
   313  		t.Errorf("0<<5 == %d, want 0", got)
   314  	}
   315  	if got := ofz64r64(5); got != 0 {
   316  		t.Errorf("0>>5 == %d, want 0", got)
   317  	}
   318  	if got := ofz64r32(5); got != 0 {
   319  		t.Errorf("0>>5 == %d, want 0", got)
   320  	}
   321  	if got := ofz64r16(5); got != 0 {
   322  		t.Errorf("0>>5 == %d, want 0", got)
   323  	}
   324  	if got := ofz64r8(5); got != 0 {
   325  		t.Errorf("0>>5 == %d, want 0", got)
   326  	}
   327  	if got := ofz64ur64(5); got != 0 {
   328  		t.Errorf("0>>>5 == %d, want 0", got)
   329  	}
   330  	if got := ofz64ur32(5); got != 0 {
   331  		t.Errorf("0>>>5 == %d, want 0", got)
   332  	}
   333  	if got := ofz64ur16(5); got != 0 {
   334  		t.Errorf("0>>>5 == %d, want 0", got)
   335  	}
   336  	if got := ofz64ur8(5); got != 0 {
   337  		t.Errorf("0>>>5 == %d, want 0", got)
   338  	}
   339  
   340  	if got := ofz32l64(5); got != 0 {
   341  		t.Errorf("0<<5 == %d, want 0", got)
   342  	}
   343  	if got := ofz32l32(5); got != 0 {
   344  		t.Errorf("0<<5 == %d, want 0", got)
   345  	}
   346  	if got := ofz32l16(5); got != 0 {
   347  		t.Errorf("0<<5 == %d, want 0", got)
   348  	}
   349  	if got := ofz32l8(5); got != 0 {
   350  		t.Errorf("0<<5 == %d, want 0", got)
   351  	}
   352  	if got := ofz32r64(5); got != 0 {
   353  		t.Errorf("0>>5 == %d, want 0", got)
   354  	}
   355  	if got := ofz32r32(5); got != 0 {
   356  		t.Errorf("0>>5 == %d, want 0", got)
   357  	}
   358  	if got := ofz32r16(5); got != 0 {
   359  		t.Errorf("0>>5 == %d, want 0", got)
   360  	}
   361  	if got := ofz32r8(5); got != 0 {
   362  		t.Errorf("0>>5 == %d, want 0", got)
   363  	}
   364  	if got := ofz32ur64(5); got != 0 {
   365  		t.Errorf("0>>>5 == %d, want 0", got)
   366  	}
   367  	if got := ofz32ur32(5); got != 0 {
   368  		t.Errorf("0>>>5 == %d, want 0", got)
   369  	}
   370  	if got := ofz32ur16(5); got != 0 {
   371  		t.Errorf("0>>>5 == %d, want 0", got)
   372  	}
   373  	if got := ofz32ur8(5); got != 0 {
   374  		t.Errorf("0>>>5 == %d, want 0", got)
   375  	}
   376  
   377  	if got := ofz16l64(5); got != 0 {
   378  		t.Errorf("0<<5 == %d, want 0", got)
   379  	}
   380  	if got := ofz16l32(5); got != 0 {
   381  		t.Errorf("0<<5 == %d, want 0", got)
   382  	}
   383  	if got := ofz16l16(5); got != 0 {
   384  		t.Errorf("0<<5 == %d, want 0", got)
   385  	}
   386  	if got := ofz16l8(5); got != 0 {
   387  		t.Errorf("0<<5 == %d, want 0", got)
   388  	}
   389  	if got := ofz16r64(5); got != 0 {
   390  		t.Errorf("0>>5 == %d, want 0", got)
   391  	}
   392  	if got := ofz16r32(5); got != 0 {
   393  		t.Errorf("0>>5 == %d, want 0", got)
   394  	}
   395  	if got := ofz16r16(5); got != 0 {
   396  		t.Errorf("0>>5 == %d, want 0", got)
   397  	}
   398  	if got := ofz16r8(5); got != 0 {
   399  		t.Errorf("0>>5 == %d, want 0", got)
   400  	}
   401  	if got := ofz16ur64(5); got != 0 {
   402  		t.Errorf("0>>>5 == %d, want 0", got)
   403  	}
   404  	if got := ofz16ur32(5); got != 0 {
   405  		t.Errorf("0>>>5 == %d, want 0", got)
   406  	}
   407  	if got := ofz16ur16(5); got != 0 {
   408  		t.Errorf("0>>>5 == %d, want 0", got)
   409  	}
   410  	if got := ofz16ur8(5); got != 0 {
   411  		t.Errorf("0>>>5 == %d, want 0", got)
   412  	}
   413  
   414  	if got := ofz8l64(5); got != 0 {
   415  		t.Errorf("0<<5 == %d, want 0", got)
   416  	}
   417  	if got := ofz8l32(5); got != 0 {
   418  		t.Errorf("0<<5 == %d, want 0", got)
   419  	}
   420  	if got := ofz8l16(5); got != 0 {
   421  		t.Errorf("0<<5 == %d, want 0", got)
   422  	}
   423  	if got := ofz8l8(5); got != 0 {
   424  		t.Errorf("0<<5 == %d, want 0", got)
   425  	}
   426  	if got := ofz8r64(5); got != 0 {
   427  		t.Errorf("0>>5 == %d, want 0", got)
   428  	}
   429  	if got := ofz8r32(5); got != 0 {
   430  		t.Errorf("0>>5 == %d, want 0", got)
   431  	}
   432  	if got := ofz8r16(5); got != 0 {
   433  		t.Errorf("0>>5 == %d, want 0", got)
   434  	}
   435  	if got := ofz8r8(5); got != 0 {
   436  		t.Errorf("0>>5 == %d, want 0", got)
   437  	}
   438  	if got := ofz8ur64(5); got != 0 {
   439  		t.Errorf("0>>>5 == %d, want 0", got)
   440  	}
   441  	if got := ofz8ur32(5); got != 0 {
   442  		t.Errorf("0>>>5 == %d, want 0", got)
   443  	}
   444  	if got := ofz8ur16(5); got != 0 {
   445  		t.Errorf("0>>>5 == %d, want 0", got)
   446  	}
   447  	if got := ofz8ur8(5); got != 0 {
   448  		t.Errorf("0>>>5 == %d, want 0", got)
   449  	}
   450  }
   451  
   452  //go:noinline
   453  func byz64l(n int64) int64 {
   454  	return n << 0
   455  }
   456  
   457  //go:noinline
   458  func byz64r(n int64) int64 {
   459  	return n >> 0
   460  }
   461  
   462  //go:noinline
   463  func byz64ur(n uint64) uint64 {
   464  	return n >> 0
   465  }
   466  
   467  //go:noinline
   468  func byz32l(n int32) int32 {
   469  	return n << 0
   470  }
   471  
   472  //go:noinline
   473  func byz32r(n int32) int32 {
   474  	return n >> 0
   475  }
   476  
   477  //go:noinline
   478  func byz32ur(n uint32) uint32 {
   479  	return n >> 0
   480  }
   481  
   482  //go:noinline
   483  func byz16l(n int16) int16 {
   484  	return n << 0
   485  }
   486  
   487  //go:noinline
   488  func byz16r(n int16) int16 {
   489  	return n >> 0
   490  }
   491  
   492  //go:noinline
   493  func byz16ur(n uint16) uint16 {
   494  	return n >> 0
   495  }
   496  
   497  //go:noinline
   498  func byz8l(n int8) int8 {
   499  	return n << 0
   500  }
   501  
   502  //go:noinline
   503  func byz8r(n int8) int8 {
   504  	return n >> 0
   505  }
   506  
   507  //go:noinline
   508  func byz8ur(n uint8) uint8 {
   509  	return n >> 0
   510  }
   511  
   512  func TestShiftByZero(t *testing.T) {
   513  	{
   514  		var n int64 = 0x5555555555555555
   515  		if got := byz64l(n); got != n {
   516  			t.Errorf("%x<<0 == %x, want %x", n, got, n)
   517  		}
   518  		if got := byz64r(n); got != n {
   519  			t.Errorf("%x>>0 == %x, want %x", n, got, n)
   520  		}
   521  	}
   522  	{
   523  		var n uint64 = 0xaaaaaaaaaaaaaaaa
   524  		if got := byz64ur(n); got != n {
   525  			t.Errorf("%x>>>0 == %x, want %x", n, got, n)
   526  		}
   527  	}
   528  
   529  	{
   530  		var n int32 = 0x55555555
   531  		if got := byz32l(n); got != n {
   532  			t.Errorf("%x<<0 == %x, want %x", n, got, n)
   533  		}
   534  		if got := byz32r(n); got != n {
   535  			t.Errorf("%x>>0 == %x, want %x", n, got, n)
   536  		}
   537  	}
   538  	{
   539  		var n uint32 = 0xaaaaaaaa
   540  		if got := byz32ur(n); got != n {
   541  			t.Errorf("%x>>>0 == %x, want %x", n, got, n)
   542  		}
   543  	}
   544  
   545  	{
   546  		var n int16 = 0x5555
   547  		if got := byz16l(n); got != n {
   548  			t.Errorf("%x<<0 == %x, want %x", n, got, n)
   549  		}
   550  		if got := byz16r(n); got != n {
   551  			t.Errorf("%x>>0 == %x, want %x", n, got, n)
   552  		}
   553  	}
   554  	{
   555  		var n uint16 = 0xaaaa
   556  		if got := byz16ur(n); got != n {
   557  			t.Errorf("%x>>>0 == %x, want %x", n, got, n)
   558  		}
   559  	}
   560  
   561  	{
   562  		var n int8 = 0x55
   563  		if got := byz8l(n); got != n {
   564  			t.Errorf("%x<<0 == %x, want %x", n, got, n)
   565  		}
   566  		if got := byz8r(n); got != n {
   567  			t.Errorf("%x>>0 == %x, want %x", n, got, n)
   568  		}
   569  	}
   570  	{
   571  		var n uint8 = 0x55
   572  		if got := byz8ur(n); got != n {
   573  			t.Errorf("%x>>>0 == %x, want %x", n, got, n)
   574  		}
   575  	}
   576  }
   577  
   578  //go:noinline
   579  func two64l(x int64) int64 {
   580  	return x << 1 << 1
   581  }
   582  
   583  //go:noinline
   584  func two64r(x int64) int64 {
   585  	return x >> 1 >> 1
   586  }
   587  
   588  //go:noinline
   589  func two64ur(x uint64) uint64 {
   590  	return x >> 1 >> 1
   591  }
   592  
   593  //go:noinline
   594  func two32l(x int32) int32 {
   595  	return x << 1 << 1
   596  }
   597  
   598  //go:noinline
   599  func two32r(x int32) int32 {
   600  	return x >> 1 >> 1
   601  }
   602  
   603  //go:noinline
   604  func two32ur(x uint32) uint32 {
   605  	return x >> 1 >> 1
   606  }
   607  
   608  //go:noinline
   609  func two16l(x int16) int16 {
   610  	return x << 1 << 1
   611  }
   612  
   613  //go:noinline
   614  func two16r(x int16) int16 {
   615  	return x >> 1 >> 1
   616  }
   617  
   618  //go:noinline
   619  func two16ur(x uint16) uint16 {
   620  	return x >> 1 >> 1
   621  }
   622  
   623  //go:noinline
   624  func two8l(x int8) int8 {
   625  	return x << 1 << 1
   626  }
   627  
   628  //go:noinline
   629  func two8r(x int8) int8 {
   630  	return x >> 1 >> 1
   631  }
   632  
   633  //go:noinline
   634  func two8ur(x uint8) uint8 {
   635  	return x >> 1 >> 1
   636  }
   637  
   638  func TestShiftCombine(t *testing.T) {
   639  	if got, want := two64l(4), int64(16); want != got {
   640  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   641  	}
   642  	if got, want := two64r(64), int64(16); want != got {
   643  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   644  	}
   645  	if got, want := two64ur(64), uint64(16); want != got {
   646  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   647  	}
   648  	if got, want := two32l(4), int32(16); want != got {
   649  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   650  	}
   651  	if got, want := two32r(64), int32(16); want != got {
   652  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   653  	}
   654  	if got, want := two32ur(64), uint32(16); want != got {
   655  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   656  	}
   657  	if got, want := two16l(4), int16(16); want != got {
   658  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   659  	}
   660  	if got, want := two16r(64), int16(16); want != got {
   661  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   662  	}
   663  	if got, want := two16ur(64), uint16(16); want != got {
   664  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   665  	}
   666  	if got, want := two8l(4), int8(16); want != got {
   667  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   668  	}
   669  	if got, want := two8r(64), int8(16); want != got {
   670  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   671  	}
   672  	if got, want := two8ur(64), uint8(16); want != got {
   673  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   674  	}
   675  
   676  }
   677  
   678  //go:noinline
   679  func three64l(x int64) int64 {
   680  	return x << 3 >> 1 << 2
   681  }
   682  
   683  //go:noinline
   684  func three64ul(x uint64) uint64 {
   685  	return x << 3 >> 1 << 2
   686  }
   687  
   688  //go:noinline
   689  func three64r(x int64) int64 {
   690  	return x >> 3 << 1 >> 2
   691  }
   692  
   693  //go:noinline
   694  func three64ur(x uint64) uint64 {
   695  	return x >> 3 << 1 >> 2
   696  }
   697  
   698  //go:noinline
   699  func three32l(x int32) int32 {
   700  	return x << 3 >> 1 << 2
   701  }
   702  
   703  //go:noinline
   704  func three32ul(x uint32) uint32 {
   705  	return x << 3 >> 1 << 2
   706  }
   707  
   708  //go:noinline
   709  func three32r(x int32) int32 {
   710  	return x >> 3 << 1 >> 2
   711  }
   712  
   713  //go:noinline
   714  func three32ur(x uint32) uint32 {
   715  	return x >> 3 << 1 >> 2
   716  }
   717  
   718  //go:noinline
   719  func three16l(x int16) int16 {
   720  	return x << 3 >> 1 << 2
   721  }
   722  
   723  //go:noinline
   724  func three16ul(x uint16) uint16 {
   725  	return x << 3 >> 1 << 2
   726  }
   727  
   728  //go:noinline
   729  func three16r(x int16) int16 {
   730  	return x >> 3 << 1 >> 2
   731  }
   732  
   733  //go:noinline
   734  func three16ur(x uint16) uint16 {
   735  	return x >> 3 << 1 >> 2
   736  }
   737  
   738  //go:noinline
   739  func three8l(x int8) int8 {
   740  	return x << 3 >> 1 << 2
   741  }
   742  
   743  //go:noinline
   744  func three8ul(x uint8) uint8 {
   745  	return x << 3 >> 1 << 2
   746  }
   747  
   748  //go:noinline
   749  func three8r(x int8) int8 {
   750  	return x >> 3 << 1 >> 2
   751  }
   752  
   753  //go:noinline
   754  func three8ur(x uint8) uint8 {
   755  	return x >> 3 << 1 >> 2
   756  }
   757  
   758  func TestShiftCombine3(t *testing.T) {
   759  	if got, want := three64l(4), int64(64); want != got {
   760  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   761  	}
   762  	if got, want := three64ul(4), uint64(64); want != got {
   763  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   764  	}
   765  	if got, want := three64r(64), int64(4); want != got {
   766  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   767  	}
   768  	if got, want := three64ur(64), uint64(4); want != got {
   769  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   770  	}
   771  	if got, want := three32l(4), int32(64); want != got {
   772  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   773  	}
   774  	if got, want := three32ul(4), uint32(64); want != got {
   775  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   776  	}
   777  	if got, want := three32r(64), int32(4); want != got {
   778  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   779  	}
   780  	if got, want := three32ur(64), uint32(4); want != got {
   781  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   782  	}
   783  	if got, want := three16l(4), int16(64); want != got {
   784  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   785  	}
   786  	if got, want := three16ul(4), uint16(64); want != got {
   787  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   788  	}
   789  	if got, want := three16r(64), int16(4); want != got {
   790  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   791  	}
   792  	if got, want := three16ur(64), uint16(4); want != got {
   793  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   794  	}
   795  	if got, want := three8l(4), int8(64); want != got {
   796  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   797  	}
   798  	if got, want := three8ul(4), uint8(64); want != got {
   799  		t.Errorf("4<<1<<1 == %d, want %d", got, want)
   800  	}
   801  	if got, want := three8r(64), int8(4); want != got {
   802  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   803  	}
   804  	if got, want := three8ur(64), uint8(4); want != got {
   805  		t.Errorf("64>>1>>1 == %d, want %d", got, want)
   806  	}
   807  }
   808  
   809  var (
   810  	one64  int64  = 1
   811  	one64u uint64 = 1
   812  	one32  int32  = 1
   813  	one32u uint32 = 1
   814  	one16  int16  = 1
   815  	one16u uint16 = 1
   816  	one8   int8   = 1
   817  	one8u  uint8  = 1
   818  )
   819  
   820  func TestShiftLargeCombine(t *testing.T) {
   821  	var N uint64 = 0x8000000000000000
   822  	if one64<<N<<N == 1 {
   823  		t.Errorf("shift overflow mishandled")
   824  	}
   825  	if one64>>N>>N == 1 {
   826  		t.Errorf("shift overflow mishandled")
   827  	}
   828  	if one64u>>N>>N == 1 {
   829  		t.Errorf("shift overflow mishandled")
   830  	}
   831  	if one32<<N<<N == 1 {
   832  		t.Errorf("shift overflow mishandled")
   833  	}
   834  	if one32>>N>>N == 1 {
   835  		t.Errorf("shift overflow mishandled")
   836  	}
   837  	if one32u>>N>>N == 1 {
   838  		t.Errorf("shift overflow mishandled")
   839  	}
   840  	if one16<<N<<N == 1 {
   841  		t.Errorf("shift overflow mishandled")
   842  	}
   843  	if one16>>N>>N == 1 {
   844  		t.Errorf("shift overflow mishandled")
   845  	}
   846  	if one16u>>N>>N == 1 {
   847  		t.Errorf("shift overflow mishandled")
   848  	}
   849  	if one8<<N<<N == 1 {
   850  		t.Errorf("shift overflow mishandled")
   851  	}
   852  	if one8>>N>>N == 1 {
   853  		t.Errorf("shift overflow mishandled")
   854  	}
   855  	if one8u>>N>>N == 1 {
   856  		t.Errorf("shift overflow mishandled")
   857  	}
   858  }
   859  
   860  func TestShiftLargeCombine3(t *testing.T) {
   861  	var N uint64 = 0x8000000000000001
   862  	if one64<<N>>2<<N == 1 {
   863  		t.Errorf("shift overflow mishandled")
   864  	}
   865  	if one64u<<N>>2<<N == 1 {
   866  		t.Errorf("shift overflow mishandled")
   867  	}
   868  	if one64>>N<<2>>N == 1 {
   869  		t.Errorf("shift overflow mishandled")
   870  	}
   871  	if one64u>>N<<2>>N == 1 {
   872  		t.Errorf("shift overflow mishandled")
   873  	}
   874  	if one32<<N>>2<<N == 1 {
   875  		t.Errorf("shift overflow mishandled")
   876  	}
   877  	if one32u<<N>>2<<N == 1 {
   878  		t.Errorf("shift overflow mishandled")
   879  	}
   880  	if one32>>N<<2>>N == 1 {
   881  		t.Errorf("shift overflow mishandled")
   882  	}
   883  	if one32u>>N<<2>>N == 1 {
   884  		t.Errorf("shift overflow mishandled")
   885  	}
   886  	if one16<<N>>2<<N == 1 {
   887  		t.Errorf("shift overflow mishandled")
   888  	}
   889  	if one16u<<N>>2<<N == 1 {
   890  		t.Errorf("shift overflow mishandled")
   891  	}
   892  	if one16>>N<<2>>N == 1 {
   893  		t.Errorf("shift overflow mishandled")
   894  	}
   895  	if one16u>>N<<2>>N == 1 {
   896  		t.Errorf("shift overflow mishandled")
   897  	}
   898  	if one8<<N>>2<<N == 1 {
   899  		t.Errorf("shift overflow mishandled")
   900  	}
   901  	if one8u<<N>>2<<N == 1 {
   902  		t.Errorf("shift overflow mishandled")
   903  	}
   904  	if one8>>N<<2>>N == 1 {
   905  		t.Errorf("shift overflow mishandled")
   906  	}
   907  	if one8u>>N<<2>>N == 1 {
   908  		t.Errorf("shift overflow mishandled")
   909  	}
   910  }
   911  
   912  func TestShiftGeneric(t *testing.T) {
   913  	for _, test := range [...]struct {
   914  		valueWidth int
   915  		signed     bool
   916  		shiftWidth int
   917  		left       bool
   918  		f          interface{}
   919  	}{
   920  		{64, true, 64, true, func(n int64, s uint64) int64 { return n << s }},
   921  		{64, true, 64, false, func(n int64, s uint64) int64 { return n >> s }},
   922  		{64, false, 64, false, func(n uint64, s uint64) uint64 { return n >> s }},
   923  		{64, true, 32, true, func(n int64, s uint32) int64 { return n << s }},
   924  		{64, true, 32, false, func(n int64, s uint32) int64 { return n >> s }},
   925  		{64, false, 32, false, func(n uint64, s uint32) uint64 { return n >> s }},
   926  		{64, true, 16, true, func(n int64, s uint16) int64 { return n << s }},
   927  		{64, true, 16, false, func(n int64, s uint16) int64 { return n >> s }},
   928  		{64, false, 16, false, func(n uint64, s uint16) uint64 { return n >> s }},
   929  		{64, true, 8, true, func(n int64, s uint8) int64 { return n << s }},
   930  		{64, true, 8, false, func(n int64, s uint8) int64 { return n >> s }},
   931  		{64, false, 8, false, func(n uint64, s uint8) uint64 { return n >> s }},
   932  
   933  		{32, true, 64, true, func(n int32, s uint64) int32 { return n << s }},
   934  		{32, true, 64, false, func(n int32, s uint64) int32 { return n >> s }},
   935  		{32, false, 64, false, func(n uint32, s uint64) uint32 { return n >> s }},
   936  		{32, true, 32, true, func(n int32, s uint32) int32 { return n << s }},
   937  		{32, true, 32, false, func(n int32, s uint32) int32 { return n >> s }},
   938  		{32, false, 32, false, func(n uint32, s uint32) uint32 { return n >> s }},
   939  		{32, true, 16, true, func(n int32, s uint16) int32 { return n << s }},
   940  		{32, true, 16, false, func(n int32, s uint16) int32 { return n >> s }},
   941  		{32, false, 16, false, func(n uint32, s uint16) uint32 { return n >> s }},
   942  		{32, true, 8, true, func(n int32, s uint8) int32 { return n << s }},
   943  		{32, true, 8, false, func(n int32, s uint8) int32 { return n >> s }},
   944  		{32, false, 8, false, func(n uint32, s uint8) uint32 { return n >> s }},
   945  
   946  		{16, true, 64, true, func(n int16, s uint64) int16 { return n << s }},
   947  		{16, true, 64, false, func(n int16, s uint64) int16 { return n >> s }},
   948  		{16, false, 64, false, func(n uint16, s uint64) uint16 { return n >> s }},
   949  		{16, true, 32, true, func(n int16, s uint32) int16 { return n << s }},
   950  		{16, true, 32, false, func(n int16, s uint32) int16 { return n >> s }},
   951  		{16, false, 32, false, func(n uint16, s uint32) uint16 { return n >> s }},
   952  		{16, true, 16, true, func(n int16, s uint16) int16 { return n << s }},
   953  		{16, true, 16, false, func(n int16, s uint16) int16 { return n >> s }},
   954  		{16, false, 16, false, func(n uint16, s uint16) uint16 { return n >> s }},
   955  		{16, true, 8, true, func(n int16, s uint8) int16 { return n << s }},
   956  		{16, true, 8, false, func(n int16, s uint8) int16 { return n >> s }},
   957  		{16, false, 8, false, func(n uint16, s uint8) uint16 { return n >> s }},
   958  
   959  		{8, true, 64, true, func(n int8, s uint64) int8 { return n << s }},
   960  		{8, true, 64, false, func(n int8, s uint64) int8 { return n >> s }},
   961  		{8, false, 64, false, func(n uint8, s uint64) uint8 { return n >> s }},
   962  		{8, true, 32, true, func(n int8, s uint32) int8 { return n << s }},
   963  		{8, true, 32, false, func(n int8, s uint32) int8 { return n >> s }},
   964  		{8, false, 32, false, func(n uint8, s uint32) uint8 { return n >> s }},
   965  		{8, true, 16, true, func(n int8, s uint16) int8 { return n << s }},
   966  		{8, true, 16, false, func(n int8, s uint16) int8 { return n >> s }},
   967  		{8, false, 16, false, func(n uint8, s uint16) uint8 { return n >> s }},
   968  		{8, true, 8, true, func(n int8, s uint8) int8 { return n << s }},
   969  		{8, true, 8, false, func(n int8, s uint8) int8 { return n >> s }},
   970  		{8, false, 8, false, func(n uint8, s uint8) uint8 { return n >> s }},
   971  	} {
   972  		fv := reflect.ValueOf(test.f)
   973  		var args [2]reflect.Value
   974  		for i := 0; i < test.valueWidth; i++ {
   975  			// Build value to be shifted.
   976  			var n int64 = 1
   977  			for j := 0; j < i; j++ {
   978  				n <<= 1
   979  			}
   980  			args[0] = reflect.ValueOf(n).Convert(fv.Type().In(0))
   981  			for s := 0; s <= test.shiftWidth; s++ {
   982  				args[1] = reflect.ValueOf(s).Convert(fv.Type().In(1))
   983  
   984  				// Compute desired result. We're testing variable shifts
   985  				// assuming constant shifts are correct.
   986  				r := n
   987  				var op string
   988  				switch {
   989  				case test.left:
   990  					op = "<<"
   991  					for j := 0; j < s; j++ {
   992  						r <<= 1
   993  					}
   994  					switch test.valueWidth {
   995  					case 32:
   996  						r = int64(int32(r))
   997  					case 16:
   998  						r = int64(int16(r))
   999  					case 8:
  1000  						r = int64(int8(r))
  1001  					}
  1002  				case test.signed:
  1003  					op = ">>"
  1004  					switch test.valueWidth {
  1005  					case 32:
  1006  						r = int64(int32(r))
  1007  					case 16:
  1008  						r = int64(int16(r))
  1009  					case 8:
  1010  						r = int64(int8(r))
  1011  					}
  1012  					for j := 0; j < s; j++ {
  1013  						r >>= 1
  1014  					}
  1015  				default:
  1016  					op = ">>>"
  1017  					for j := 0; j < s; j++ {
  1018  						r = int64(uint64(r) >> 1)
  1019  					}
  1020  				}
  1021  
  1022  				// Call function.
  1023  				res := fv.Call(args[:])[0].Convert(reflect.ValueOf(r).Type())
  1024  
  1025  				if res.Int() != r {
  1026  					t.Errorf("%s%dx%d(%x,%x)=%x, want %x", op, test.valueWidth, test.shiftWidth, n, s, res.Int(), r)
  1027  				}
  1028  			}
  1029  		}
  1030  	}
  1031  }
  1032  
  1033  var shiftSink64 int64
  1034  
  1035  func BenchmarkShiftArithmeticRight(b *testing.B) {
  1036  	x := shiftSink64
  1037  	for i := 0; i < b.N; i++ {
  1038  		x = x >> (i & 63)
  1039  	}
  1040  	shiftSink64 = x
  1041  }
  1042  
  1043  //go:noinline
  1044  func incorrectRotate1(x, c uint64) uint64 {
  1045  	// This should not compile to a rotate instruction.
  1046  	return x<<c | x>>(64-c)
  1047  }
  1048  
  1049  //go:noinline
  1050  func incorrectRotate2(x uint64) uint64 {
  1051  	var c uint64 = 66
  1052  	// This should not compile to a rotate instruction.
  1053  	return x<<c | x>>(64-c)
  1054  }
  1055  
  1056  func TestIncorrectRotate(t *testing.T) {
  1057  	if got := incorrectRotate1(1, 66); got != 0 {
  1058  		t.Errorf("got %x want 0", got)
  1059  	}
  1060  	if got := incorrectRotate2(1); got != 0 {
  1061  		t.Errorf("got %x want 0", got)
  1062  	}
  1063  }
  1064  
  1065  //go:noinline
  1066  func variableShiftOverflow64x8(x int64, y, z uint8) (a, b, c int64) {
  1067  	// Verify junk bits are ignored when doing a variable shift.
  1068  	return x >> (y + z), x << (y + z), int64(uint64(x) >> (y + z))
  1069  }
  1070  
  1071  //go:noinline
  1072  func variableShiftOverflow32x8(x int32, y, z uint8) (a, b, c int32) {
  1073  	// Verify junk bits are ignored when doing a variable shift.
  1074  	return x >> (y + z), x << (y + z), int32(uint32(x) >> (y + z))
  1075  }
  1076  
  1077  //go:noinline
  1078  func variableShiftOverflow16x8(x int16, y, z uint8) (a, b, c int16) {
  1079  	// Verify junk bits are ignored when doing a variable shift.
  1080  	return x >> (y + z), x << (y + z), int16(uint16(x) >> (y + z))
  1081  }
  1082  
  1083  //go:noinline
  1084  func variableShiftOverflow8x8(x int8, y, z uint8) (a, b, c int8) {
  1085  	// Verify junk bits are ignored when doing a variable shift.
  1086  	return x >> (y + z), x << (y + z), int8(uint8(x) >> (y + z))
  1087  }
  1088  
  1089  //go:noinline
  1090  func variableShiftOverflow64x16(x int64, y, z uint16) (a, b, c int64) {
  1091  	// Verify junk bits are ignored when doing a variable shift.
  1092  	return x >> (y + z), x << (y + z), int64(uint64(x) >> (y + z))
  1093  }
  1094  
  1095  //go:noinline
  1096  func variableShiftOverflow32x16(x int32, y, z uint16) (a, b, c int32) {
  1097  	// Verify junk bits are ignored when doing a variable shift.
  1098  	return x >> (y + z), x << (y + z), int32(uint32(x) >> (y + z))
  1099  }
  1100  
  1101  //go:noinline
  1102  func variableShiftOverflow16x16(x int16, y, z uint16) (a, b, c int16) {
  1103  	// Verify junk bits are ignored when doing a variable shift.
  1104  	return x >> (y + z), x << (y + z), int16(uint16(x) >> (y + z))
  1105  }
  1106  
  1107  //go:noinline
  1108  func variableShiftOverflow8x16(x int8, y, z uint16) (a, b, c int8) {
  1109  	// Verify junk bits are ignored when doing a variable shift.
  1110  	return x >> (y + z), x << (y + z), int8(uint8(x) >> (y + z))
  1111  }
  1112  
  1113  //go:noinline
  1114  func makeU8(x uint64) uint8 {
  1115  	// Ensure the upper portions of the register are clear before testing large shift values
  1116  	// using non-native types (e.g uint8 on PPC64).
  1117  	return uint8(x)
  1118  }
  1119  
  1120  //go:noinline
  1121  func makeU16(x uint64) uint16 {
  1122  	// Ensure the upper portions of the register are clear before testing large shift values
  1123  	// using non-native types (e.g uint8 on PPC64).
  1124  	return uint16(x)
  1125  }
  1126  
  1127  func TestShiftOverflow(t *testing.T) {
  1128  	if v, w, z := variableShiftOverflow64x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x7fffffffffffffe0 {
  1129  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffffffffffe0", v, w, z)
  1130  	}
  1131  	if v, w, z := variableShiftOverflow32x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x7fffffe0 {
  1132  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffe0", v, w, z)
  1133  	}
  1134  	if v, w, z := variableShiftOverflow16x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x7fe0 {
  1135  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fe0", v, w, z)
  1136  	}
  1137  	if v, w, z := variableShiftOverflow8x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x60 {
  1138  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x60", v, w, z)
  1139  	}
  1140  	if v, w, z := variableShiftOverflow64x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x7fffffffffffffe0 {
  1141  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffffffffffe0", v, w, z)
  1142  	}
  1143  	if v, w, z := variableShiftOverflow32x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x7fffffe0 {
  1144  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffe0,", v, w, z)
  1145  	}
  1146  	if v, w, z := variableShiftOverflow16x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x7fe0 {
  1147  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fe0", v, w, z)
  1148  	}
  1149  	if v, w, z := variableShiftOverflow8x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x60 {
  1150  		t.Errorf("got %d %d 0x%x, expected -32 -128 0x60", v, w, z)
  1151  	}
  1152  }
  1153  

View as plain text