Source file test/codegen/noextend.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  import "math/bits"
    10  
    11  var sval64 [8]int64
    12  var sval32 [8]int32
    13  var sval16 [8]int16
    14  var sval8 [8]int8
    15  var val64 [8]uint64
    16  var val32 [8]uint32
    17  var val16 [8]uint16
    18  var val8 [8]uint8
    19  
    20  // Avoid zero/sign extensions following a load
    21  // which has extended the value correctly.
    22  // Note: No tests are done for int8 since
    23  // an extra extension is usually needed due to
    24  // no signed byte load.
    25  
    26  func set16(x8 int8, u8 *uint8, y8 int8, z8 uint8) {
    27  	// Truncate not needed, load does sign/zero extend
    28  
    29  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
    30  	val16[0] = uint16(*u8)
    31  
    32  	// AND not needed due to size
    33  	// ppc64x:-"ANDCC"
    34  	sval16[1] = 255 & int16(x8+y8)
    35  
    36  	// ppc64x:-"ANDCC"
    37  	val16[1] = 255 & uint16(*u8+z8)
    38  
    39  }
    40  func shiftidx(u8 *uint8, x16 *int16, u16 *uint16) {
    41  
    42  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
    43  	val16[0] = uint16(sval16[*u8>>2])
    44  
    45  	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
    46  	sval16[1] = int16(val16[*x16>>1])
    47  
    48  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
    49  	val16[1] = uint16(sval16[*u16>>2])
    50  
    51  }
    52  
    53  func setnox(x8 int8, u8 *uint8, y8 *int8, z8 *uint8, x16 *int16, u16 *uint16, x32 *int32, u32 *uint32) {
    54  
    55  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
    56  	val16[0] = uint16(*u8)
    57  
    58  	// AND not needed due to size
    59  	// ppc64x:-"ANDCC"
    60  	sval16[1] = 255 & int16(x8+*y8)
    61  
    62  	// ppc64x:-"ANDCC"
    63  	val16[1] = 255 & uint16(*u8+*z8)
    64  
    65  	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
    66  	sval32[1] = int32(*x16)
    67  
    68  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
    69  	val32[0] = uint32(*u8)
    70  
    71  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
    72  	val32[1] = uint32(*u16)
    73  
    74  	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
    75  	sval64[1] = int64(*x16)
    76  
    77  	// ppc64x:-"MOVW\tR\\d+,\\sR\\d+"
    78  	sval64[2] = int64(*x32)
    79  
    80  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
    81  	val64[0] = uint64(*u8)
    82  
    83  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
    84  	val64[1] = uint64(*u16)
    85  
    86  	// ppc64x:-"MOVWZ\tR\\d+,\\sR\\d+"
    87  	val64[2] = uint64(*u32)
    88  }
    89  
    90  func cmp16(u8 *uint8, x32 *int32, u32 *uint32, x64 *int64, u64 *uint64) bool {
    91  
    92  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
    93  	if uint16(*u8) == val16[0] {
    94  		return true
    95  	}
    96  
    97  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
    98  	if uint16(*u32>>16) == val16[0] {
    99  		return true
   100  	}
   101  
   102  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
   103  	if uint16(*u64>>48) == val16[0] {
   104  		return true
   105  	}
   106  
   107  	// Verify the truncates are using the correct sign.
   108  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
   109  	if int16(*x32) == sval16[0] {
   110  		return true
   111  	}
   112  
   113  	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
   114  	if uint16(*u32) == val16[0] {
   115  		return true
   116  	}
   117  
   118  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
   119  	if int16(*x64) == sval16[0] {
   120  		return true
   121  	}
   122  
   123  	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
   124  	if uint16(*u64) == val16[0] {
   125  		return true
   126  	}
   127  
   128  	return false
   129  }
   130  
   131  func cmp32(u8 *uint8, x16 *int16, u16 *uint16, x64 *int64, u64 *uint64) bool {
   132  
   133  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
   134  	if uint32(*u8) == val32[0] {
   135  		return true
   136  	}
   137  
   138  	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
   139  	if int32(*x16) == sval32[0] {
   140  		return true
   141  	}
   142  
   143  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
   144  	if uint32(*u16) == val32[0] {
   145  		return true
   146  	}
   147  
   148  	// Verify the truncates are using the correct sign.
   149  	// ppc64x:-"MOVWZ\tR\\d+,\\sR\\d+"
   150  	if int32(*x64) == sval32[0] {
   151  		return true
   152  	}
   153  
   154  	// ppc64x:-"MOVW\tR\\d+,\\sR\\d+"
   155  	if uint32(*u64) == val32[0] {
   156  		return true
   157  	}
   158  
   159  	return false
   160  }
   161  
   162  func cmp64(u8 *uint8, x16 *int16, u16 *uint16, x32 *int32, u32 *uint32) bool {
   163  
   164  	// ppc64x:-"MOVBZ\tR\\d+,\\sR\\d+"
   165  	if uint64(*u8) == val64[0] {
   166  		return true
   167  	}
   168  
   169  	// ppc64x:-"MOVH\tR\\d+,\\sR\\d+"
   170  	if int64(*x16) == sval64[0] {
   171  		return true
   172  	}
   173  
   174  	// ppc64x:-"MOVHZ\tR\\d+,\\sR\\d+"
   175  	if uint64(*u16) == val64[0] {
   176  		return true
   177  	}
   178  
   179  	// ppc64x:-"MOVW\tR\\d+,\\sR\\d+"
   180  	if int64(*x32) == sval64[0] {
   181  		return true
   182  	}
   183  
   184  	// ppc64x:-"MOVWZ\tR\\d+,\\sR\\d+"
   185  	if uint64(*u32) == val64[0] {
   186  		return true
   187  	}
   188  	return false
   189  }
   190  
   191  // no unsign extension following 32 bits ops
   192  
   193  func noUnsignEXT(t1, t2, t3, t4 uint32, k int64) uint64 {
   194  	var ret uint64
   195  
   196  	// arm64:"RORW",-"MOVWU"
   197  	ret += uint64(bits.RotateLeft32(t1, 7))
   198  
   199  	// arm64:"MULW",-"MOVWU"
   200  	ret *= uint64(t1 * t2)
   201  
   202  	// arm64:"MNEGW",-"MOVWU"
   203  	ret += uint64(-t1 * t3)
   204  
   205  	// arm64:"UDIVW",-"MOVWU"
   206  	ret += uint64(t1 / t4)
   207  
   208  	// arm64:-"MOVWU"
   209  	ret += uint64(t2 % t3)
   210  
   211  	// arm64:"MSUBW",-"MOVWU"
   212  	ret += uint64(t1 - t2*t3)
   213  
   214  	// arm64:"MADDW",-"MOVWU"
   215  	ret += uint64(t3*t4 + t2)
   216  
   217  	// arm64:"REVW",-"MOVWU"
   218  	ret += uint64(bits.ReverseBytes32(t1))
   219  
   220  	// arm64:"RBITW",-"MOVWU"
   221  	ret += uint64(bits.Reverse32(t1))
   222  
   223  	// arm64:"CLZW",-"MOVWU"
   224  	ret += uint64(bits.LeadingZeros32(t1))
   225  
   226  	// arm64:"REV16W",-"MOVWU"
   227  	ret += uint64(((t1 & 0xff00ff00) >> 8) | ((t1 & 0x00ff00ff) << 8))
   228  
   229  	// arm64:"EXTRW",-"MOVWU"
   230  	ret += uint64((t1 << 25) | (t2 >> 7))
   231  
   232  	return ret
   233  }
   234  
   235  // no sign extension when the upper bits of the result are zero
   236  
   237  func noSignEXT(x int) int64 {
   238  	t1 := int32(x)
   239  
   240  	var ret int64
   241  
   242  	// arm64:-"MOVW"
   243  	ret += int64(t1 & 1)
   244  
   245  	// arm64:-"MOVW"
   246  	ret += int64(int32(x & 0x7fffffff))
   247  
   248  	// arm64:-"MOVH"
   249  	ret += int64(int16(x & 0x7fff))
   250  
   251  	// arm64:-"MOVB"
   252  	ret += int64(int8(x & 0x7f))
   253  
   254  	return ret
   255  }
   256  
   257  // corner cases that sign extension must not be omitted
   258  
   259  func shouldSignEXT(x int) int64 {
   260  	t1 := int32(x)
   261  
   262  	var ret int64
   263  
   264  	// arm64:"MOVW"
   265  	ret += int64(t1 & (-1))
   266  
   267  	// arm64:"MOVW"
   268  	ret += int64(int32(x & 0x80000000))
   269  
   270  	// arm64:"MOVW"
   271  	ret += int64(int32(x & 0x1100000011111111))
   272  
   273  	// arm64:"MOVH"
   274  	ret += int64(int16(x & 0x1100000000001111))
   275  
   276  	// arm64:"MOVB"
   277  	ret += int64(int8(x & 0x1100000000000011))
   278  
   279  	return ret
   280  }
   281  
   282  func noIntermediateExtension(a, b, c uint32) uint32 {
   283  	// arm64:-"MOVWU"
   284  	return a*b*9 + c
   285  }
   286  

View as plain text