Repository: go
Issue: runtime: redundant allocation after type assertion
Labels: Performance,NeedsInvestigation,compiler/runtime

### Go version

go version go1.21.4 linux/amd64

### What operating system and processor architecture are you using (`go env`)?

```shell
GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOVCS=''
GOVERSION='go1.21.4'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
```


### What did you do?

Consider example snippet and a benchmark:
```go
package main

import (
	"fmt"
	"testing"
)

var gv any

func sink(v any) {
	gv = v
}

func setString(v any) {
	if s, ok := v.(string); ok {
		sink(s)
	} else {
		sink(fmt.Sprint(v))
		panic("unreachable")
	}
}

func setString2(v any) {
	if _, ok := v.(string); ok {
		sink(v)
	} else {
		sink(fmt.Sprint(v))
		panic("unreachable")
	}
}

func BenchmarkInterfaceToString(b *testing.B) {
	var v any
	v = "hello"

	b.Run("setString", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			setString(v)
		}
	})

	b.Run("setString2", func(b *testing.B) {
		for i := 0; i < b.N; i++ {
			setString2(v)
		}
	})
}

```



### What did you expect to see?

No difference in benchmarks for `setString` and `setString2`.


### What did you see instead?

`setString` allocates to convert string `s` into `any` argument of `sink` although `s` is obtained from `any` `v`.

```
$ go test ./stringany_test.go -run=NONE -bench=Benchmark -benchmem
goos: linux
goarch: amd64
cpu: Intel(R) Core(TM) i5-8350U CPU @ 1.70GHz
BenchmarkInterfaceToString/setString-8          16101618                67.47 ns/op           16 B/op          1 allocs/op
BenchmarkInterfaceToString/setString2-8         194076378                5.335 ns/op           0 B/op          0 allocs/op
PASS
ok      command-line-arguments  2.828s
```

```
$ go test ./stringany_test.go -run=NONE -bench='BenchmarkInterfaceToString/setString$' -count=10 -benchmem -cpuprofile=/tmp/cpu.pprof
$ go tool pprof /tmp/cpu.pprof 
File: main.test
Type: cpu
Time: Dec 4, 2023 at 10:54pm (CET)
Duration: 13.85s, Total samples = 14.37s (103.76%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 12120ms, 84.34% of 14370ms total
Dropped 113 nodes (cum <= 71.85ms)
Showing top 10 nodes out of 38
      flat  flat%   sum%        cum   cum%
    4470ms 31.11% 31.11%    10610ms 73.83%  runtime.mallocgc
    1380ms  9.60% 40.71%     1430ms  9.95%  runtime.writeHeapBits.flush
    1310ms  9.12% 49.83%     1310ms  9.12%  runtime.nextFreeFast (inline)
    1060ms  7.38% 57.20%    11670ms 81.21%  runtime.convTstring
    1050ms  7.31% 64.51%    13860ms 96.45%  command-line-arguments.BenchmarkInterfaceToString.func1
     930ms  6.47% 70.98%     2780ms 19.35%  runtime.heapBitsSetType
     690ms  4.80% 75.78%    12810ms 89.14%  command-line-arguments.setString
     440ms  3.06% 78.84%      450ms  3.13%  command-line-arguments.sink (inline)
     400ms  2.78% 81.63%      400ms  2.78%  runtime.acquirem (inline)
     390ms  2.71% 84.34%      440ms  3.06%  runtime.deductAssistCredit
```

Perhaps compiler could figure out that `s` is `v` and pass `v` to `sink` instead.