Source file test/codegen/shift.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  // ------------------ //
    10  //   constant shifts  //
    11  // ------------------ //
    12  
    13  func lshConst64x64(v int64) int64 {
    14  	// ppc64x:"SLD"
    15  	// riscv64:"SLLI",-"AND",-"SLTIU"
    16  	return v << uint64(33)
    17  }
    18  
    19  func rshConst64Ux64(v uint64) uint64 {
    20  	// ppc64x:"SRD"
    21  	// riscv64:"SRLI\t",-"AND",-"SLTIU"
    22  	return v >> uint64(33)
    23  }
    24  
    25  func rshConst64Ux64Overflow32(v uint32) uint64 {
    26  	// riscv64:"MOV\t\\$0,",-"SRL"
    27  	return uint64(v) >> 32
    28  }
    29  
    30  func rshConst64Ux64Overflow16(v uint16) uint64 {
    31  	// riscv64:"MOV\t\\$0,",-"SRL"
    32  	return uint64(v) >> 16
    33  }
    34  
    35  func rshConst64Ux64Overflow8(v uint8) uint64 {
    36  	// riscv64:"MOV\t\\$0,",-"SRL"
    37  	return uint64(v) >> 8
    38  }
    39  
    40  func rshConst64x64(v int64) int64 {
    41  	// ppc64x:"SRAD"
    42  	// riscv64:"SRAI\t",-"OR",-"SLTIU"
    43  	return v >> uint64(33)
    44  }
    45  
    46  func rshConst64x64Overflow32(v int32) int64 {
    47  	// riscv64:"SRAIW",-"SLLI",-"SRAI\t"
    48  	return int64(v) >> 32
    49  }
    50  
    51  func rshConst64x64Overflow16(v int16) int64 {
    52  	// riscv64:"SLLI","SRAI",-"SRAIW"
    53  	return int64(v) >> 16
    54  }
    55  
    56  func rshConst64x64Overflow8(v int8) int64 {
    57  	// riscv64:"SLLI","SRAI",-"SRAIW"
    58  	return int64(v) >> 8
    59  }
    60  
    61  func lshConst32x64(v int32) int32 {
    62  	// ppc64x:"SLW"
    63  	// riscv64:"SLLI",-"AND",-"SLTIU", -"MOVW"
    64  	return v << uint64(29)
    65  }
    66  
    67  func rshConst32Ux64(v uint32) uint32 {
    68  	// ppc64x:"SRW"
    69  	// riscv64:"SRLIW",-"AND",-"SLTIU", -"MOVW"
    70  	return v >> uint64(29)
    71  }
    72  
    73  func rshConst32x64(v int32) int32 {
    74  	// ppc64x:"SRAW"
    75  	// riscv64:"SRAIW",-"OR",-"SLTIU", -"MOVW"
    76  	return v >> uint64(29)
    77  }
    78  
    79  func lshConst64x32(v int64) int64 {
    80  	// ppc64x:"SLD"
    81  	// riscv64:"SLLI",-"AND",-"SLTIU"
    82  	return v << uint32(33)
    83  }
    84  
    85  func rshConst64Ux32(v uint64) uint64 {
    86  	// ppc64x:"SRD"
    87  	// riscv64:"SRLI\t",-"AND",-"SLTIU"
    88  	return v >> uint32(33)
    89  }
    90  
    91  func rshConst64x32(v int64) int64 {
    92  	// ppc64x:"SRAD"
    93  	// riscv64:"SRAI\t",-"OR",-"SLTIU"
    94  	return v >> uint32(33)
    95  }
    96  
    97  // ------------------ //
    98  //   masked shifts    //
    99  // ------------------ //
   100  
   101  func lshMask64x64(v int64, s uint64) int64 {
   102  	// arm64:"LSL",-"AND"
   103  	// ppc64x:"RLDICL",-"ORN",-"ISEL"
   104  	// riscv64:"SLL",-"AND\t",-"SLTIU"
   105  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   106  	return v << (s & 63)
   107  }
   108  
   109  func rshMask64Ux64(v uint64, s uint64) uint64 {
   110  	// arm64:"LSR",-"AND",-"CSEL"
   111  	// ppc64x:"RLDICL",-"ORN",-"ISEL"
   112  	// riscv64:"SRL\t",-"AND\t",-"SLTIU"
   113  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   114  	return v >> (s & 63)
   115  }
   116  
   117  func rshMask64x64(v int64, s uint64) int64 {
   118  	// arm64:"ASR",-"AND",-"CSEL"
   119  	// ppc64x:"RLDICL",-"ORN",-"ISEL"
   120  	// riscv64:"SRA\t",-"OR",-"SLTIU"
   121  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   122  	return v >> (s & 63)
   123  }
   124  
   125  func lshMask32x64(v int32, s uint64) int32 {
   126  	// arm64:"LSL",-"AND"
   127  	// ppc64x:"ISEL",-"ORN"
   128  	// riscv64:"SLL",-"AND\t",-"SLTIU"
   129  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   130  	return v << (s & 63)
   131  }
   132  
   133  func rshMask32Ux64(v uint32, s uint64) uint32 {
   134  	// arm64:"LSR",-"AND"
   135  	// ppc64x:"ISEL",-"ORN"
   136  	// riscv64:"SRLW","SLTIU","NEG","AND\t",-"SRL\t"
   137  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   138  	return v >> (s & 63)
   139  }
   140  
   141  func rsh5Mask32Ux64(v uint32, s uint64) uint32 {
   142  	// riscv64:"SRLW",-"AND\t",-"SLTIU",-"SRL\t"
   143  	return v >> (s & 31)
   144  }
   145  
   146  func rshMask32x64(v int32, s uint64) int32 {
   147  	// arm64:"ASR",-"AND"
   148  	// ppc64x:"ISEL",-"ORN"
   149  	// riscv64:"SRAW","OR","SLTIU"
   150  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   151  	return v >> (s & 63)
   152  }
   153  
   154  func rsh5Mask32x64(v int32, s uint64) int32 {
   155  	// riscv64:"SRAW",-"OR",-"SLTIU"
   156  	return v >> (s & 31)
   157  }
   158  
   159  func lshMask64x32(v int64, s uint32) int64 {
   160  	// arm64:"LSL",-"AND"
   161  	// ppc64x:"RLDICL",-"ORN"
   162  	// riscv64:"SLL",-"AND\t",-"SLTIU"
   163  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   164  	return v << (s & 63)
   165  }
   166  
   167  func rshMask64Ux32(v uint64, s uint32) uint64 {
   168  	// arm64:"LSR",-"AND",-"CSEL"
   169  	// ppc64x:"RLDICL",-"ORN"
   170  	// riscv64:"SRL\t",-"AND\t",-"SLTIU"
   171  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   172  	return v >> (s & 63)
   173  }
   174  
   175  func rshMask64x32(v int64, s uint32) int64 {
   176  	// arm64:"ASR",-"AND",-"CSEL"
   177  	// ppc64x:"RLDICL",-"ORN",-"ISEL"
   178  	// riscv64:"SRA\t",-"OR",-"SLTIU"
   179  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   180  	return v >> (s & 63)
   181  }
   182  
   183  func lshMask64x32Ext(v int64, s int32) int64 {
   184  	// ppc64x:"RLDICL",-"ORN",-"ISEL"
   185  	// riscv64:"SLL",-"AND\t",-"SLTIU"
   186  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   187  	return v << uint(s&63)
   188  }
   189  
   190  func rshMask64Ux32Ext(v uint64, s int32) uint64 {
   191  	// ppc64x:"RLDICL",-"ORN",-"ISEL"
   192  	// riscv64:"SRL\t",-"AND\t",-"SLTIU"
   193  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   194  	return v >> uint(s&63)
   195  }
   196  
   197  func rshMask64x32Ext(v int64, s int32) int64 {
   198  	// ppc64x:"RLDICL",-"ORN",-"ISEL"
   199  	// riscv64:"SRA\t",-"OR",-"SLTIU"
   200  	// s390x:-"RISBGZ",-"AND",-"LOCGR"
   201  	return v >> uint(s&63)
   202  }
   203  
   204  // --------------- //
   205  //  signed shifts  //
   206  // --------------- //
   207  
   208  // We do want to generate a test + panicshift for these cases.
   209  func lshSigned(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
   210  	// amd64:"TESTB"
   211  	_ = x << v8
   212  	// amd64:"TESTW"
   213  	_ = x << v16
   214  	// amd64:"TESTL"
   215  	_ = x << v32
   216  	// amd64:"TESTQ"
   217  	_ = x << v64
   218  }
   219  
   220  // We want to avoid generating a test + panicshift for these cases.
   221  func lshSignedMasked(v8 int8, v16 int16, v32 int32, v64 int64, x int) {
   222  	// amd64:-"TESTB"
   223  	_ = x << (v8 & 7)
   224  	// amd64:-"TESTW"
   225  	_ = x << (v16 & 15)
   226  	// amd64:-"TESTL"
   227  	_ = x << (v32 & 31)
   228  	// amd64:-"TESTQ"
   229  	_ = x << (v64 & 63)
   230  }
   231  
   232  // ------------------ //
   233  //   bounded shifts   //
   234  // ------------------ //
   235  
   236  func lshGuarded64(v int64, s uint) int64 {
   237  	if s < 64 {
   238  		// riscv64:"SLL",-"AND",-"SLTIU"
   239  		// s390x:-"RISBGZ",-"AND",-"LOCGR"
   240  		// wasm:-"Select",-".*LtU"
   241  		// arm64:"LSL",-"CSEL"
   242  		return v << s
   243  	}
   244  	panic("shift too large")
   245  }
   246  
   247  func rshGuarded64U(v uint64, s uint) uint64 {
   248  	if s < 64 {
   249  		// riscv64:"SRL\t",-"AND",-"SLTIU"
   250  		// s390x:-"RISBGZ",-"AND",-"LOCGR"
   251  		// wasm:-"Select",-".*LtU"
   252  		// arm64:"LSR",-"CSEL"
   253  		return v >> s
   254  	}
   255  	panic("shift too large")
   256  }
   257  
   258  func rshGuarded64(v int64, s uint) int64 {
   259  	if s < 64 {
   260  		// riscv64:"SRA\t",-"OR",-"SLTIU"
   261  		// s390x:-"RISBGZ",-"AND",-"LOCGR"
   262  		// wasm:-"Select",-".*LtU"
   263  		// arm64:"ASR",-"CSEL"
   264  		return v >> s
   265  	}
   266  	panic("shift too large")
   267  }
   268  
   269  func provedUnsignedShiftLeft(val64 uint64, val32 uint32, val16 uint16, val8 uint8, shift int) (r1 uint64, r2 uint32, r3 uint16, r4 uint8) {
   270  	if shift >= 0 && shift < 64 {
   271  		// arm64:"LSL",-"CSEL"
   272  		r1 = val64 << shift
   273  	}
   274  	if shift >= 0 && shift < 32 {
   275  		// arm64:"LSL",-"CSEL"
   276  		r2 = val32 << shift
   277  	}
   278  	if shift >= 0 && shift < 16 {
   279  		// arm64:"LSL",-"CSEL"
   280  		r3 = val16 << shift
   281  	}
   282  	if shift >= 0 && shift < 8 {
   283  		// arm64:"LSL",-"CSEL"
   284  		r4 = val8 << shift
   285  	}
   286  	return r1, r2, r3, r4
   287  }
   288  
   289  func provedSignedShiftLeft(val64 int64, val32 int32, val16 int16, val8 int8, shift int) (r1 int64, r2 int32, r3 int16, r4 int8) {
   290  	if shift >= 0 && shift < 64 {
   291  		// arm64:"LSL",-"CSEL"
   292  		r1 = val64 << shift
   293  	}
   294  	if shift >= 0 && shift < 32 {
   295  		// arm64:"LSL",-"CSEL"
   296  		r2 = val32 << shift
   297  	}
   298  	if shift >= 0 && shift < 16 {
   299  		// arm64:"LSL",-"CSEL"
   300  		r3 = val16 << shift
   301  	}
   302  	if shift >= 0 && shift < 8 {
   303  		// arm64:"LSL",-"CSEL"
   304  		r4 = val8 << shift
   305  	}
   306  	return r1, r2, r3, r4
   307  }
   308  
   309  func provedUnsignedShiftRight(val64 uint64, val32 uint32, val16 uint16, val8 uint8, shift int) (r1 uint64, r2 uint32, r3 uint16, r4 uint8) {
   310  	if shift >= 0 && shift < 64 {
   311  		// arm64:"LSR",-"CSEL"
   312  		r1 = val64 >> shift
   313  	}
   314  	if shift >= 0 && shift < 32 {
   315  		// arm64:"LSR",-"CSEL"
   316  		r2 = val32 >> shift
   317  	}
   318  	if shift >= 0 && shift < 16 {
   319  		// arm64:"LSR",-"CSEL"
   320  		r3 = val16 >> shift
   321  	}
   322  	if shift >= 0 && shift < 8 {
   323  		// arm64:"LSR",-"CSEL"
   324  		r4 = val8 >> shift
   325  	}
   326  	return r1, r2, r3, r4
   327  }
   328  
   329  func provedSignedShiftRight(val64 int64, val32 int32, val16 int16, val8 int8, shift int) (r1 int64, r2 int32, r3 int16, r4 int8) {
   330  	if shift >= 0 && shift < 64 {
   331  		// arm64:"ASR",-"CSEL"
   332  		r1 = val64 >> shift
   333  	}
   334  	if shift >= 0 && shift < 32 {
   335  		// arm64:"ASR",-"CSEL"
   336  		r2 = val32 >> shift
   337  	}
   338  	if shift >= 0 && shift < 16 {
   339  		// arm64:"ASR",-"CSEL"
   340  		r3 = val16 >> shift
   341  	}
   342  	if shift >= 0 && shift < 8 {
   343  		// arm64:"ASR",-"CSEL"
   344  		r4 = val8 >> shift
   345  	}
   346  	return r1, r2, r3, r4
   347  }
   348  
   349  func checkUnneededTrunc(tab *[100000]uint32, d uint64, v uint32, h uint16, b byte) (uint32, uint64) {
   350  
   351  	// ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
   352  	f := tab[byte(v)^b]
   353  	// ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
   354  	f += tab[byte(v)&b]
   355  	// ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
   356  	f += tab[byte(v)|b]
   357  	// ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
   358  	f += tab[uint16(v)&h]
   359  	// ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
   360  	f += tab[uint16(v)^h]
   361  	// ppc64x:-".*RLWINM",-".*RLDICR",".*CLRLSLDI"
   362  	f += tab[uint16(v)|h]
   363  	// ppc64x:-".*AND",-"RLDICR",".*CLRLSLDI"
   364  	f += tab[v&0xff]
   365  	// ppc64x:-".*AND",".*CLRLSLWI"
   366  	f += 2 * uint32(uint16(d))
   367  	// ppc64x:-".*AND",-"RLDICR",".*CLRLSLDI"
   368  	g := 2 * uint64(uint32(d))
   369  	return f, g
   370  }
   371  
   372  func checkCombinedShifts(v8 uint8, v16 uint16, v32 uint32, x32 int32, v64 uint64) (uint8, uint16, uint32, uint64, int64) {
   373  
   374  	// ppc64x:-"AND","CLRLSLWI"
   375  	f := (v8 & 0xF) << 2
   376  	// ppc64x:"CLRLSLWI"
   377  	f += byte(v16) << 3
   378  	// ppc64x:-"AND","CLRLSLWI"
   379  	g := (v16 & 0xFF) << 3
   380  	// ppc64x:-"AND","CLRLSLWI"
   381  	h := (v32 & 0xFFFFF) << 2
   382  	// ppc64x:"CLRLSLDI"
   383  	i := (v64 & 0xFFFFFFFF) << 5
   384  	// ppc64x:-"CLRLSLDI"
   385  	i += (v64 & 0xFFFFFFF) << 38
   386  	// ppc64x/power9:-"CLRLSLDI"
   387  	i += (v64 & 0xFFFF00) << 10
   388  	// ppc64x/power9:-"SLD","EXTSWSLI"
   389  	j := int64(x32+32) * 8
   390  	return f, g, h, i, j
   391  }
   392  
   393  func checkWidenAfterShift(v int64, u uint64) (int64, uint64) {
   394  
   395  	// ppc64x:-".*MOVW"
   396  	f := int32(v >> 32)
   397  	// ppc64x:".*MOVW"
   398  	f += int32(v >> 31)
   399  	// ppc64x:-".*MOVH"
   400  	g := int16(v >> 48)
   401  	// ppc64x:".*MOVH"
   402  	g += int16(v >> 30)
   403  	// ppc64x:-".*MOVH"
   404  	g += int16(f >> 16)
   405  	// ppc64x:-".*MOVB"
   406  	h := int8(v >> 56)
   407  	// ppc64x:".*MOVB"
   408  	h += int8(v >> 28)
   409  	// ppc64x:-".*MOVB"
   410  	h += int8(f >> 24)
   411  	// ppc64x:".*MOVB"
   412  	h += int8(f >> 16)
   413  	return int64(h), uint64(g)
   414  }
   415  
   416  func checkShiftAndMask32(v []uint32) {
   417  	i := 0
   418  
   419  	// ppc64x: "RLWNM\t[$]24, R[0-9]+, [$]12, [$]19, R[0-9]+"
   420  	v[i] = (v[i] & 0xFF00000) >> 8
   421  	i++
   422  	// ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]22, [$]29, R[0-9]+"
   423  	v[i] = (v[i] & 0xFF00) >> 6
   424  	i++
   425  	// ppc64x: "MOVW\tR0"
   426  	v[i] = (v[i] & 0xFF) >> 8
   427  	i++
   428  	// ppc64x: "MOVW\tR0"
   429  	v[i] = (v[i] & 0xF000000) >> 28
   430  	i++
   431  	// ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]24, [$]31, R[0-9]+"
   432  	v[i] = (v[i] >> 6) & 0xFF
   433  	i++
   434  	// ppc64x: "RLWNM\t[$]26, R[0-9]+, [$]12, [$]19, R[0-9]+"
   435  	v[i] = (v[i] >> 6) & 0xFF000
   436  	i++
   437  	// ppc64x: "MOVW\tR0"
   438  	v[i] = (v[i] >> 20) & 0xFF000
   439  	i++
   440  	// ppc64x: "MOVW\tR0"
   441  	v[i] = (v[i] >> 24) & 0xFF00
   442  	i++
   443  }
   444  
   445  func checkMergedShifts32(a [256]uint32, b [256]uint64, u uint32, v uint32) {
   446  	// ppc64x: -"CLRLSLDI", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]29, R[0-9]+"
   447  	a[0] = a[uint8(v>>24)]
   448  	// ppc64x: -"CLRLSLDI", "RLWNM\t[$]11, R[0-9]+, [$]21, [$]28, R[0-9]+"
   449  	b[0] = b[uint8(v>>24)]
   450  	// ppc64x: -"CLRLSLDI", "RLWNM\t[$]15, R[0-9]+, [$]21, [$]28, R[0-9]+"
   451  	b[1] = b[(v>>20)&0xFF]
   452  	// ppc64x: -"SLD", "RLWNM\t[$]10, R[0-9]+, [$]22, [$]28, R[0-9]+"
   453  	b[2] = b[v>>25]
   454  }
   455  
   456  // 128 bit shifts
   457  
   458  func check128bitShifts(x, y uint64, bits uint) (uint64, uint64) {
   459  	s := bits & 63
   460  	ŝ := (64 - bits) & 63
   461  	// check that the shift operation has two commas (three operands)
   462  	// amd64:"SHRQ.*,.*,"
   463  	shr := x>>s | y<<ŝ
   464  	// amd64:"SHLQ.*,.*,"
   465  	shl := x<<s | y>>ŝ
   466  	return shr, shl
   467  }
   468  
   469  func checkShiftToMask(u []uint64, s []int64) {
   470  	// amd64:-"SHR",-"SHL","ANDQ"
   471  	u[0] = u[0] >> 5 << 5
   472  	// amd64:-"SAR",-"SHL","ANDQ"
   473  	s[0] = s[0] >> 5 << 5
   474  	// amd64:-"SHR",-"SHL","ANDQ"
   475  	u[1] = u[1] << 5 >> 5
   476  }
   477  

View as plain text