| // asmcheck |
| |
| // Copyright 2019 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // These tests check code generation of switch statements. |
| |
| package codegen |
| |
| // see issue 33934 |
| func f(x string) int { |
| // amd64:-`cmpstring` |
| switch x { |
| case "": |
| return -1 |
| case "1", "2", "3": |
| return -2 |
| default: |
| return -3 |
| } |
| } |
| |
| // use jump tables for 8+ string cases |
| // Using multiple return values prevent lookup tables. |
| func squareJump(x int) (int, int) { |
| // amd64:`JMP \(.*\)\(.*\)$` |
| // arm64:`MOVD \(R.*\)\(R.*<<3\)` `JMP \(R.*\)$` |
| // loong64: `ALSLV` `MOVV` `JMP` |
| switch x { |
| case 1: |
| return 1, 1 |
| case 2: |
| return 4, 2 |
| case 3: |
| return 9, 3 |
| case 4: |
| return 16, 4 |
| case 5: |
| return 25, 5 |
| case 6: |
| return 36, 6 |
| case 7: |
| return 49, 7 |
| case 8: |
| return 64, 8 |
| default: |
| return x * x, x |
| } |
| } |
| |
| // use lookup tables for 8+ int cases returning constants |
| func squareLookup(x int) int { |
| // amd64:`LEAQ .*\(SB\)` `MOVQ .*\(.*\)\(.*\*8\)` -`JMP \(.*\)\(.*\)$` |
| // arm64:`MOVD \(R.*\)\(R.*<<3\)` -`JMP \(R.*\)$` |
| // loong64:`SLLV` `MOVV \(R.*\)\(R.*\)` -`ALSLV` |
| switch x { |
| case 1: |
| return 1 |
| case 2: |
| return 4 |
| case 3: |
| return 9 |
| case 4: |
| return 16 |
| case 5: |
| return 25 |
| case 6: |
| return 36 |
| case 7: |
| return 49 |
| case 8: |
| return 64 |
| default: |
| return x * x |
| } |
| } |
| |
| // use jump tables for 8+ string lengths |
| func length(x string) int { |
| // amd64:`JMP \(.*\)\(.*\)$` |
| // arm64:`MOVD \(R.*\)\(R.*<<3\)` `JMP \(R.*\)$` |
| // loong64:`ALSLV` `MOVV` `JMP` |
| switch x { |
| case "a": |
| return 1 |
| case "bb": |
| return 2 |
| case "ccc": |
| return 3 |
| case "dddd": |
| return 4 |
| case "eeeee": |
| return 5 |
| case "ffffff": |
| return 6 |
| case "ggggggg": |
| return 7 |
| case "hhhhhhhh": |
| return 8 |
| default: |
| return len(x) |
| } |
| } |
| |
| // Use single-byte ordered comparisons for binary searching strings. |
| // See issue 53333. |
| func mimetype(ext string) string { |
| // amd64: `CMPB 1\(.*\), \$104$` -`cmpstring` |
| // arm64: `MOVB 1\(R.*\), R.*$` `CMPW \$104, R.*$` -`cmpstring` |
| switch ext { |
| // amd64: `CMPL \(.*\), \$1836345390$` |
| // arm64: `MOVD \$1836345390` `CMPW R.*, R.*$` |
| case ".htm": |
| return "A" |
| // amd64: `CMPL \(.*\), \$1953457454$` |
| // arm64: `MOVD \$1953457454` `CMPW R.*, R.*$` |
| case ".eot": |
| return "B" |
| // amd64: `CMPL \(.*\), \$1735815982$` |
| // arm64: `MOVD \$1735815982` `CMPW R.*, R.*$` |
| case ".svg": |
| return "C" |
| // amd64: `CMPL \(.*\), \$1718907950$` |
| // arm64: `MOVD \$1718907950` `CMPW R.*, R.*$` |
| case ".ttf": |
| return "D" |
| default: |
| return "" |
| } |
| } |
| |
| // use jump tables for type switches to concrete types. |
| func typeSwitch(x any) int { |
| // amd64:`JMP \(.*\)\(.*\)$` |
| // arm64:`MOVD \(R.*\)\(R.*<<3\)` `JMP \(R.*\)$` |
| switch x.(type) { |
| case int: |
| return 0 |
| case int8: |
| return 1 |
| case int16: |
| return 2 |
| case int32: |
| return 3 |
| case int64: |
| return 4 |
| } |
| return 7 |
| } |
| |
| type I interface { |
| foo() |
| } |
| type J interface { |
| bar() |
| } |
| type IJ interface { |
| I |
| J |
| } |
| type K interface { |
| baz() |
| } |
| |
| // use a runtime call for type switches to interface types. |
| func interfaceSwitch(x any) int { |
| // amd64:`CALL runtime.interfaceSwitch` `MOVL 16\(AX\)` `MOVQ 8\(.*\)(.*\*8)` |
| // arm64:`CALL runtime.interfaceSwitch` `LDAR` `MOVWU 16\(R0\)` `MOVD \(R.*\)\(R.*\)` |
| switch x.(type) { |
| case I: |
| return 1 |
| case J: |
| return 2 |
| default: |
| return 3 |
| } |
| } |
| |
| func interfaceSwitch2(x K) int { |
| // amd64:`CALL runtime.interfaceSwitch` `MOVL 16\(AX\)` `MOVQ 8\(.*\)(.*\*8)` |
| // arm64:`CALL runtime.interfaceSwitch` `LDAR` `MOVWU 16\(R0\)` `MOVD \(R.*\)\(R.*\)` |
| switch x.(type) { |
| case I: |
| return 1 |
| case J: |
| return 2 |
| default: |
| return 3 |
| } |
| } |
| |
| func interfaceCast(x any) int { |
| // amd64:`CALL runtime.typeAssert` `MOVL 16\(AX\)` `MOVQ 8\(.*\)(.*\*1)` |
| // arm64:`CALL runtime.typeAssert` `LDAR` `MOVWU 16\(R0\)` `MOVD \(R.*\)\(R.*\)` |
| if _, ok := x.(I); ok { |
| return 3 |
| } |
| return 5 |
| } |
| |
| func interfaceCast2(x K) int { |
| // amd64:`CALL runtime.typeAssert` `MOVL 16\(AX\)` `MOVQ 8\(.*\)(.*\*1)` |
| // arm64:`CALL runtime.typeAssert` `LDAR` `MOVWU 16\(R0\)` `MOVD \(R.*\)\(R.*\)` |
| if _, ok := x.(I); ok { |
| return 3 |
| } |
| return 5 |
| } |
| |
| func interfaceConv(x IJ) I { |
| // amd64:`CALL runtime.typeAssert` `MOVL 16\(AX\)` `MOVQ 8\(.*\)(.*\*1)` |
| // arm64:`CALL runtime.typeAssert` `LDAR` `MOVWU 16\(R0\)` `MOVD \(R.*\)\(R.*\)` |
| return x |
| } |
| |
| // Make sure we can constant fold after inlining. See issue 71699. |
| func stringSwitchInlineable(s string) { |
| switch s { |
| case "foo", "bar", "baz", "goo": |
| default: |
| println("no") |
| } |
| } |
| func stringSwitch() { |
| // amd64:-"CMP" -"CALL" |
| // arm64:-"CMP" -"CALL" |
| stringSwitchInlineable("foo") |
| } |