Source file test/codegen/condmove.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  func cmovint(c int) int {
    10  	x := c + 4
    11  	if x < 0 {
    12  		x = 182
    13  	}
    14  	// amd64:"CMOVQLT"
    15  	// arm64:"CSEL\tLT"
    16  	// ppc64:"ISEL\t[$]0"
    17  	// ppc64le:"ISEL\t[$]0"
    18  	// wasm:"Select"
    19  	return x
    20  }
    21  
    22  func cmovchan(x, y chan int) chan int {
    23  	if x != y {
    24  		x = y
    25  	}
    26  	// amd64:"CMOVQNE"
    27  	// arm64:"CSEL\tNE"
    28  	// ppc64:"ISEL\t[$]2"
    29  	// ppc64le:"ISEL\t[$]2"
    30  	// wasm:"Select"
    31  	return x
    32  }
    33  
    34  func cmovuintptr(x, y uintptr) uintptr {
    35  	if x < y {
    36  		x = -y
    37  	}
    38  	// amd64:"CMOVQ(HI|CS)"
    39  	// arm64:"CSNEG\tLS"
    40  	// ppc64:"ISEL\t[$]1"
    41  	// ppc64le:"ISEL\t[$]1"
    42  	// wasm:"Select"
    43  	return x
    44  }
    45  
    46  func cmov32bit(x, y uint32) uint32 {
    47  	if x < y {
    48  		x = -y
    49  	}
    50  	// amd64:"CMOVL(HI|CS)"
    51  	// arm64:"CSNEG\t(LS|HS)"
    52  	// ppc64:"ISEL\t[$]1"
    53  	// ppc64le:"ISEL\t[$]1"
    54  	// wasm:"Select"
    55  	return x
    56  }
    57  
    58  func cmov16bit(x, y uint16) uint16 {
    59  	if x < y {
    60  		x = -y
    61  	}
    62  	// amd64:"CMOVW(HI|CS)"
    63  	// arm64:"CSNEG\t(LS|HS)"
    64  	// ppc64:"ISEL\t[$]0"
    65  	// ppc64le:"ISEL\t[$]0"
    66  	// wasm:"Select"
    67  	return x
    68  }
    69  
    70  // Floating point comparison. For EQ/NE, we must
    71  // generate special code to handle NaNs.
    72  func cmovfloateq(x, y float64) int {
    73  	a := 128
    74  	if x == y {
    75  		a = 256
    76  	}
    77  	// amd64:"CMOVQNE","CMOVQPC"
    78  	// arm64:"CSEL\tEQ"
    79  	// ppc64:"ISEL\t[$]2"
    80  	// ppc64le:"ISEL\t[$]2"
    81  	// wasm:"Select"
    82  	return a
    83  }
    84  
    85  func cmovfloatne(x, y float64) int {
    86  	a := 128
    87  	if x != y {
    88  		a = 256
    89  	}
    90  	// amd64:"CMOVQNE","CMOVQPS"
    91  	// arm64:"CSEL\tNE"
    92  	// ppc64:"ISEL\t[$]2"
    93  	// ppc64le:"ISEL\t[$]2"
    94  	// wasm:"Select"
    95  	return a
    96  }
    97  
    98  //go:noinline
    99  func frexp(f float64) (frac float64, exp int) {
   100  	return 1.0, 4
   101  }
   102  
   103  //go:noinline
   104  func ldexp(frac float64, exp int) float64 {
   105  	return 1.0
   106  }
   107  
   108  // Generate a CMOV with a floating comparison and integer move.
   109  func cmovfloatint2(x, y float64) float64 {
   110  	yfr, yexp := 4.0, 5
   111  
   112  	r := x
   113  	for r >= y {
   114  		rfr, rexp := frexp(r)
   115  		if rfr < yfr {
   116  			rexp = rexp - 1
   117  		}
   118  		// amd64:"CMOVQHI"
   119  		// arm64:"CSEL\tMI"
   120  		// ppc64:"ISEL\t[$]0"
   121  		// ppc64le:"ISEL\t[$]0"
   122  		// wasm:"Select"
   123  		r = r - ldexp(y, rexp-yexp)
   124  	}
   125  	return r
   126  }
   127  
   128  func cmovloaded(x [4]int, y int) int {
   129  	if x[2] != 0 {
   130  		y = x[2]
   131  	} else {
   132  		y = y >> 2
   133  	}
   134  	// amd64:"CMOVQNE"
   135  	// arm64:"CSEL\tNE"
   136  	// ppc64:"ISEL\t[$]2"
   137  	// ppc64le:"ISEL\t[$]2"
   138  	// wasm:"Select"
   139  	return y
   140  }
   141  
   142  func cmovuintptr2(x, y uintptr) uintptr {
   143  	a := x * 2
   144  	if a == 0 {
   145  		a = 256
   146  	}
   147  	// amd64:"CMOVQEQ"
   148  	// arm64:"CSEL\tEQ"
   149  	// ppc64:"ISEL\t[$]2"
   150  	// ppc64le:"ISEL\t[$]2"
   151  	// wasm:"Select"
   152  	return a
   153  }
   154  
   155  // Floating point CMOVs are not supported by amd64/arm64/ppc64/ppc64le
   156  func cmovfloatmove(x, y int) float64 {
   157  	a := 1.0
   158  	if x <= y {
   159  		a = 2.0
   160  	}
   161  	// amd64:-"CMOV"
   162  	// arm64:-"CSEL"
   163  	// ppc64:-"ISEL"
   164  	// ppc64le:-"ISEL"
   165  	// wasm:-"Select"
   166  	return a
   167  }
   168  
   169  // On amd64, the following patterns trigger comparison inversion.
   170  // Test that we correctly invert the CMOV condition
   171  var gsink int64
   172  var gusink uint64
   173  
   174  func cmovinvert1(x, y int64) int64 {
   175  	if x < gsink {
   176  		y = -y
   177  	}
   178  	// amd64:"CMOVQGT"
   179  	return y
   180  }
   181  func cmovinvert2(x, y int64) int64 {
   182  	if x <= gsink {
   183  		y = -y
   184  	}
   185  	// amd64:"CMOVQGE"
   186  	return y
   187  }
   188  func cmovinvert3(x, y int64) int64 {
   189  	if x == gsink {
   190  		y = -y
   191  	}
   192  	// amd64:"CMOVQEQ"
   193  	return y
   194  }
   195  func cmovinvert4(x, y int64) int64 {
   196  	if x != gsink {
   197  		y = -y
   198  	}
   199  	// amd64:"CMOVQNE"
   200  	return y
   201  }
   202  func cmovinvert5(x, y uint64) uint64 {
   203  	if x > gusink {
   204  		y = -y
   205  	}
   206  	// amd64:"CMOVQCS"
   207  	return y
   208  }
   209  func cmovinvert6(x, y uint64) uint64 {
   210  	if x >= gusink {
   211  		y = -y
   212  	}
   213  	// amd64:"CMOVQLS"
   214  	return y
   215  }
   216  
   217  func cmovload(a []int, i int, b bool) int {
   218  	if b {
   219  		i++
   220  	}
   221  	// See issue 26306
   222  	// amd64:-"CMOVQNE"
   223  	return a[i]
   224  }
   225  
   226  func cmovstore(a []int, i int, b bool) {
   227  	if b {
   228  		i++
   229  	}
   230  	// amd64:"CMOVQNE"
   231  	a[i] = 7
   232  }
   233  
   234  var r0, r1, r2, r3, r4, r5 int
   235  
   236  func cmovinc(cond bool, a, b, c int) {
   237  	var x0, x1 int
   238  
   239  	if cond {
   240  		x0 = a
   241  	} else {
   242  		x0 = b + 1
   243  	}
   244  	// arm64:"CSINC\tNE", -"CSEL"
   245  	r0 = x0
   246  
   247  	if cond {
   248  		x1 = b + 1
   249  	} else {
   250  		x1 = a
   251  	}
   252  	// arm64:"CSINC\tEQ", -"CSEL"
   253  	r1 = x1
   254  
   255  	if cond {
   256  		c++
   257  	}
   258  	// arm64:"CSINC\tEQ", -"CSEL"
   259  	r2 = c
   260  }
   261  
   262  func cmovinv(cond bool, a, b int) {
   263  	var x0, x1 int
   264  
   265  	if cond {
   266  		x0 = a
   267  	} else {
   268  		x0 = ^b
   269  	}
   270  	// arm64:"CSINV\tNE", -"CSEL"
   271  	r0 = x0
   272  
   273  	if cond {
   274  		x1 = ^b
   275  	} else {
   276  		x1 = a
   277  	}
   278  	// arm64:"CSINV\tEQ", -"CSEL"
   279  	r1 = x1
   280  }
   281  
   282  func cmovneg(cond bool, a, b, c int) {
   283  	var x0, x1 int
   284  
   285  	if cond {
   286  		x0 = a
   287  	} else {
   288  		x0 = -b
   289  	}
   290  	// arm64:"CSNEG\tNE", -"CSEL"
   291  	r0 = x0
   292  
   293  	if cond {
   294  		x1 = -b
   295  	} else {
   296  		x1 = a
   297  	}
   298  	// arm64:"CSNEG\tEQ", -"CSEL"
   299  	r1 = x1
   300  }
   301  
   302  func cmovsetm(cond bool, x int) {
   303  	var x0, x1 int
   304  
   305  	if cond {
   306  		x0 = -1
   307  	} else {
   308  		x0 = 0
   309  	}
   310  	// arm64:"CSETM\tNE", -"CSEL"
   311  	r0 = x0
   312  
   313  	if cond {
   314  		x1 = 0
   315  	} else {
   316  		x1 = -1
   317  	}
   318  	// arm64:"CSETM\tEQ", -"CSEL"
   319  	r1 = x1
   320  }
   321  
   322  func cmovFcmp0(s, t float64, a, b int) {
   323  	var x0, x1, x2, x3, x4, x5 int
   324  
   325  	if s < t {
   326  		x0 = a
   327  	} else {
   328  		x0 = b + 1
   329  	}
   330  	// arm64:"CSINC\tMI", -"CSEL"
   331  	r0 = x0
   332  
   333  	if s <= t {
   334  		x1 = a
   335  	} else {
   336  		x1 = ^b
   337  	}
   338  	// arm64:"CSINV\tLS", -"CSEL"
   339  	r1 = x1
   340  
   341  	if s > t {
   342  		x2 = a
   343  	} else {
   344  		x2 = -b
   345  	}
   346  	// arm64:"CSNEG\tMI", -"CSEL"
   347  	r2 = x2
   348  
   349  	if s >= t {
   350  		x3 = -1
   351  	} else {
   352  		x3 = 0
   353  	}
   354  	// arm64:"CSETM\tLS", -"CSEL"
   355  	r3 = x3
   356  
   357  	if s == t {
   358  		x4 = a
   359  	} else {
   360  		x4 = b + 1
   361  	}
   362  	// arm64:"CSINC\tEQ", -"CSEL"
   363  	r4 = x4
   364  
   365  	if s != t {
   366  		x5 = a
   367  	} else {
   368  		x5 = b + 1
   369  	}
   370  	// arm64:"CSINC\tNE", -"CSEL"
   371  	r5 = x5
   372  }
   373  
   374  func cmovFcmp1(s, t float64, a, b int) {
   375  	var x0, x1, x2, x3, x4, x5 int
   376  
   377  	if s < t {
   378  		x0 = b + 1
   379  	} else {
   380  		x0 = a
   381  	}
   382  	// arm64:"CSINC\tPL", -"CSEL"
   383  	r0 = x0
   384  
   385  	if s <= t {
   386  		x1 = ^b
   387  	} else {
   388  		x1 = a
   389  	}
   390  	// arm64:"CSINV\tHI", -"CSEL"
   391  	r1 = x1
   392  
   393  	if s > t {
   394  		x2 = -b
   395  	} else {
   396  		x2 = a
   397  	}
   398  	// arm64:"CSNEG\tPL", -"CSEL"
   399  	r2 = x2
   400  
   401  	if s >= t {
   402  		x3 = 0
   403  	} else {
   404  		x3 = -1
   405  	}
   406  	// arm64:"CSETM\tHI", -"CSEL"
   407  	r3 = x3
   408  
   409  	if s == t {
   410  		x4 = b + 1
   411  	} else {
   412  		x4 = a
   413  	}
   414  	// arm64:"CSINC\tNE", -"CSEL"
   415  	r4 = x4
   416  
   417  	if s != t {
   418  		x5 = b + 1
   419  	} else {
   420  		x5 = a
   421  	}
   422  	// arm64:"CSINC\tEQ", -"CSEL"
   423  	r5 = x5
   424  }
   425  
   426  func cmovzero1(c bool) int {
   427  	var x int
   428  	if c {
   429  		x = 182
   430  	}
   431  	// loong64:"MASKEQZ", -"MASKNEZ"
   432  	return x
   433  }
   434  
   435  func cmovzero2(c bool) int {
   436  	var x int
   437  	if !c {
   438  		x = 182
   439  	}
   440  	// loong64:"MASKNEZ", -"MASKEQZ"
   441  	return x
   442  }
   443  
   444  // Conditionally selecting between a value or 0 can be done without
   445  // an extra load of 0 to a register on PPC64 by using R0 (which always
   446  // holds the value $0) instead. Verify both cases where either arg1
   447  // or arg2 is zero.
   448  func cmovzeroreg0(a, b int) int {
   449  	x := 0
   450  	if a == b {
   451  		x = a
   452  	}
   453  	// ppc64:"ISEL\t[$]2, R[0-9]+, R0, R[0-9]+"
   454  	// ppc64le:"ISEL\t[$]2, R[0-9]+, R0, R[0-9]+"
   455  	return x
   456  }
   457  
   458  func cmovzeroreg1(a, b int) int {
   459  	x := a
   460  	if a == b {
   461  		x = 0
   462  	}
   463  	// ppc64:"ISEL\t[$]2, R0, R[0-9]+, R[0-9]+"
   464  	// ppc64le:"ISEL\t[$]2, R0, R[0-9]+, R[0-9]+"
   465  	return x
   466  }
   467  

View as plain text