Repository: go
Issue: cmd/compile: doesn't inline basic funcs and doesn't optimize code after inlining
Labels: Performance,NeedsInvestigation,compiler/runtime

### Go version

go version go1.22.6 darwin/arm64

### Output of `go env` in your module/workspace:

```shell
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/xxx/Library/Caches/go-build'
GOENV='/Users/xxx/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/xxx/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/xxx/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.22.6/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.22.6/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.6'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
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'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/6n/4bnk08l915n2qsvtzm_lmtv40000gn/T/go-build2946791027=/tmp/go-build -gno-record-gcc-switches -fno-common'
```


### What did you do?

I'm trying to add a basic tracing library to our code and found out so many example when golang doesn't inline basic cases, so providing here a "simplified" to the minimum examples w/o code doing a real tracing.

### What did you see happen?

### example 1 

```
package main

import "fmt"

var level = 0

func StartSpan(name string) {
        if level&1 != 0 {
                fmt.Println("StartSpan")
        }
}

func main() {
        StartSpan("span")
}
```

`StartSpan` doesn't inline in this example in main().
gcflags -m says that './main.go:9:15: "StartSpan" escapes to heap', though it is unclear what exactly escapes here and why it is a problem for const string.

Seems this is a problem as in tracing one frequently need to provide variadic number of attributes.
Replacing `fmt.Println()` to some non-variadic function helps in this example.

### Example 2

Ok, lets make compiler to inline StartSpan by replacing Println() to a different function, but having a variadic KV list:

```
func StartSpan(name string, kv ...KV) {
        if level&1 != 0 {
                // do smth useless, just need a call to some other func here
                fn(name, kv)
        }
}

var list []KV

func fn(name string, kv []KV) {
        // do smth with kv... e.g. copy elements to some global list
        for idx := range kv {
                list = append(list, kv[idx])
        }
}

func main() {
        StartSpan("span", KV{"k1", "v1"}, KV{"k2", "v2"})
}
```

now `StartSpan` is inlined to main, but its arguments are prepared BEFORE check for `if level&1 != 0` and it takes significant amount of code like this (actually, I saw 2 pages of asm with allocations and WriteBarrier in real life):

```
main.main STEXT size=432 args=0x0 locals=0xb8 funcid=0x0 align=0x0
...
        0x001c 00028 (/tmp/test/main.go:27)     STP     (ZR, ZR), main..autotmp_6-80(SP)
        0x0020 00032 (/tmp/test/main.go:27)     STP     (ZR, ZR), main..autotmp_6-64(SP)
        0x0024 00036 (/tmp/test/main.go:27)     STP     (ZR, ZR), main..autotmp_6-48(SP)
        0x0028 00040 (/tmp/test/main.go:27)     STP     (ZR, ZR), main..autotmp_6-32(SP)
        0x002c 00044 (/tmp/test/main.go:27)     MOVD    $2, R5
        0x0030 00048 (/tmp/test/main.go:27)     MOVD    R5, main..autotmp_6-72(SP)
        0x0034 00052 (/tmp/test/main.go:27)     MOVD    $go:string."k1"(SB), R6
        0x003c 00060 (/tmp/test/main.go:27)     MOVD    R6, main..autotmp_6-80(SP)
        0x0040 00064 (/tmp/test/main.go:27)     MOVD    R5, main..autotmp_6-56(SP)
        0x0044 00068 (/tmp/test/main.go:27)     MOVD    $go:string."v1"(SB), R6
        0x004c 00076 (/tmp/test/main.go:27)     MOVD    R6, main..autotmp_6-64(SP)
        0x0050 00080 (/tmp/test/main.go:27)     MOVD    R5, main..autotmp_6-40(SP)
        0x0054 00084 (/tmp/test/main.go:27)     MOVD    $go:string."k2"(SB), R6
        0x005c 00092 (/tmp/test/main.go:27)     MOVD    R6, main..autotmp_6-48(SP)
        0x0060 00096 (/tmp/test/main.go:27)     MOVD    R5, main..autotmp_6-24(SP)
        0x0064 00100 (/tmp/test/main.go:27)     MOVD    $go:string."v2"(SB), R5
        0x006c 00108 (/tmp/test/main.go:27)     MOVD    R5, main..autotmp_6-32(SP)
        0x0070 00112 (<unknown line number>)    NOP
        0x0070 00112 (<unknown line number>)    PCDATA  $0, $-3

while the level flag is checked just here:
        
        0x0070 00112 (/tmp/test/main.go:11)     MOVD    main.level(SB), R5
        0x0078 00120 (/tmp/test/main.go:11)     PCDATA  $0, $-1
        0x0078 00120 (/tmp/test/main.go:11)     TBZ     $0, R5, 132
...
```

so it seems like compiler is absolutely incapable to detect and reorder code efficiently in situations like this... :/
I believe such situations are pretty common in loggers, tracing and other typical scenarios and it deserves optimization.

### What did you expect to see?

efficient inlining of function `StartSpan` in both examples and checking level variable BEFORE initializing lots of argument objects.