Source file test/codegen/switch.go

     1  // asmcheck
     2  
     3  // Copyright 2019 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  // These tests check code generation of switch statements.
     8  
     9  package codegen
    10  
    11  // see issue 33934
    12  func f(x string) int {
    13  	// amd64:-`cmpstring`
    14  	switch x {
    15  	case "":
    16  		return -1
    17  	case "1", "2", "3":
    18  		return -2
    19  	default:
    20  		return -3
    21  	}
    22  }
    23  
    24  // use jump tables for 8+ int cases
    25  func square(x int) int {
    26  	// amd64:`JMP\s\(.*\)\(.*\)$`
    27  	// arm64:`MOVD\s\(R.*\)\(R.*<<3\)`,`JMP\s\(R.*\)$`
    28  	// loong64: `ALSLV`,`MOVV`,`JMP`
    29  	switch x {
    30  	case 1:
    31  		return 1
    32  	case 2:
    33  		return 4
    34  	case 3:
    35  		return 9
    36  	case 4:
    37  		return 16
    38  	case 5:
    39  		return 25
    40  	case 6:
    41  		return 36
    42  	case 7:
    43  		return 49
    44  	case 8:
    45  		return 64
    46  	default:
    47  		return x * x
    48  	}
    49  }
    50  
    51  // use jump tables for 8+ string lengths
    52  func length(x string) int {
    53  	// amd64:`JMP\s\(.*\)\(.*\)$`
    54  	// arm64:`MOVD\s\(R.*\)\(R.*<<3\)`,`JMP\s\(R.*\)$`
    55  	// loong64:`ALSLV`,`MOVV`,`JMP`
    56  	switch x {
    57  	case "a":
    58  		return 1
    59  	case "bb":
    60  		return 2
    61  	case "ccc":
    62  		return 3
    63  	case "dddd":
    64  		return 4
    65  	case "eeeee":
    66  		return 5
    67  	case "ffffff":
    68  		return 6
    69  	case "ggggggg":
    70  		return 7
    71  	case "hhhhhhhh":
    72  		return 8
    73  	default:
    74  		return len(x)
    75  	}
    76  }
    77  
    78  // Use single-byte ordered comparisons for binary searching strings.
    79  // See issue 53333.
    80  func mimetype(ext string) string {
    81  	// amd64: `CMPB\s1\(.*\), \$104$`,-`cmpstring`
    82  	// arm64: `MOVB\s1\(R.*\), R.*$`, `CMPW\s\$104, R.*$`, -`cmpstring`
    83  	switch ext {
    84  	// amd64: `CMPL\s\(.*\), \$1836345390$`
    85  	// arm64: `MOVD\s\$1836345390`, `CMPW\sR.*, R.*$`
    86  	case ".htm":
    87  		return "A"
    88  	// amd64: `CMPL\s\(.*\), \$1953457454$`
    89  	// arm64: `MOVD\s\$1953457454`, `CMPW\sR.*, R.*$`
    90  	case ".eot":
    91  		return "B"
    92  	// amd64: `CMPL\s\(.*\), \$1735815982$`
    93  	// arm64: `MOVD\s\$1735815982`, `CMPW\sR.*, R.*$`
    94  	case ".svg":
    95  		return "C"
    96  	// amd64: `CMPL\s\(.*\), \$1718907950$`
    97  	// arm64: `MOVD\s\$1718907950`, `CMPW\sR.*, R.*$`
    98  	case ".ttf":
    99  		return "D"
   100  	default:
   101  		return ""
   102  	}
   103  }
   104  
   105  // use jump tables for type switches to concrete types.
   106  func typeSwitch(x any) int {
   107  	// amd64:`JMP\s\(.*\)\(.*\)$`
   108  	// arm64:`MOVD\s\(R.*\)\(R.*<<3\)`,`JMP\s\(R.*\)$`
   109  	switch x.(type) {
   110  	case int:
   111  		return 0
   112  	case int8:
   113  		return 1
   114  	case int16:
   115  		return 2
   116  	case int32:
   117  		return 3
   118  	case int64:
   119  		return 4
   120  	}
   121  	return 7
   122  }
   123  
   124  type I interface {
   125  	foo()
   126  }
   127  type J interface {
   128  	bar()
   129  }
   130  type IJ interface {
   131  	I
   132  	J
   133  }
   134  type K interface {
   135  	baz()
   136  }
   137  
   138  // use a runtime call for type switches to interface types.
   139  func interfaceSwitch(x any) int {
   140  	// amd64:`CALL runtime.interfaceSwitch`,`MOVL 16\(AX\)`,`MOVQ 8\(.*\)(.*\*8)`
   141  	// arm64:`CALL runtime.interfaceSwitch`,`LDAR`,`MOVWU 16\(R0\)`,`MOVD \(R.*\)\(R.*\)`
   142  	switch x.(type) {
   143  	case I:
   144  		return 1
   145  	case J:
   146  		return 2
   147  	default:
   148  		return 3
   149  	}
   150  }
   151  
   152  func interfaceSwitch2(x K) int {
   153  	// amd64:`CALL runtime.interfaceSwitch`,`MOVL 16\(AX\)`,`MOVQ 8\(.*\)(.*\*8)`
   154  	// arm64:`CALL runtime.interfaceSwitch`,`LDAR`,`MOVWU 16\(R0\)`,`MOVD \(R.*\)\(R.*\)`
   155  	switch x.(type) {
   156  	case I:
   157  		return 1
   158  	case J:
   159  		return 2
   160  	default:
   161  		return 3
   162  	}
   163  }
   164  
   165  func interfaceCast(x any) int {
   166  	// amd64:`CALL runtime.typeAssert`,`MOVL 16\(AX\)`,`MOVQ 8\(.*\)(.*\*1)`
   167  	// arm64:`CALL runtime.typeAssert`,`LDAR`,`MOVWU 16\(R0\)`,`MOVD \(R.*\)\(R.*\)`
   168  	if _, ok := x.(I); ok {
   169  		return 3
   170  	}
   171  	return 5
   172  }
   173  
   174  func interfaceCast2(x K) int {
   175  	// amd64:`CALL runtime.typeAssert`,`MOVL 16\(AX\)`,`MOVQ 8\(.*\)(.*\*1)`
   176  	// arm64:`CALL runtime.typeAssert`,`LDAR`,`MOVWU 16\(R0\)`,`MOVD \(R.*\)\(R.*\)`
   177  	if _, ok := x.(I); ok {
   178  		return 3
   179  	}
   180  	return 5
   181  }
   182  
   183  func interfaceConv(x IJ) I {
   184  	// amd64:`CALL runtime.typeAssert`,`MOVL 16\(AX\)`,`MOVQ 8\(.*\)(.*\*1)`
   185  	// arm64:`CALL runtime.typeAssert`,`LDAR`,`MOVWU 16\(R0\)`,`MOVD \(R.*\)\(R.*\)`
   186  	return x
   187  }
   188  
   189  // Make sure we can constant fold after inlining. See issue 71699.
   190  func stringSwitchInlineable(s string) {
   191  	switch s {
   192  	case "foo", "bar", "baz", "goo":
   193  	default:
   194  		println("no")
   195  	}
   196  }
   197  func stringSwitch() {
   198  	// amd64:-"CMP" -"CALL"
   199  	// arm64:-"CMP" -"CALL"
   200  	stringSwitchInlineable("foo")
   201  }
   202  

View as plain text