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

View as plain text