Skip to content

cmd/compile: inliner loses optimizations (and has different optimizations) for constant string args #76372

@fice-t

Description

@fice-t

Go version

go version go1.26-devel_8c41a48 Tue Nov 18 11:46:42 2025 -0800 linux/amd64

Output of go env in your module/workspace:

Workspace is `go.godbolt.org` on `x86-64 gc (tip)` as above.

What did you do?

[Code/output tested here]

Compile the following:

func constPrefixInlined(s string) bool {
    const prefix = "caddyfile"
    return len(s) >= len(prefix) && s[:len(prefix)] == prefix
}

func constPrefix(s string) bool {
    const prefix = "caddyfile"
    return innerPrefix(s, prefix)
}

// same code+result as with using strings.HasPrefix
func innerPrefix(s, prefix string) bool {
    return len(s) >= len(prefix) && s[:len(prefix)] == prefix
}

What did you see happen?

constPrefix calls runtime.memequal with go:string."caddyfile", while constPrefixInlined gets the following:

        CMPQ    BX, $9
        JLT     command-line-arguments_constPrefixInlined_pc39
        MOVQ    $7811887700212212067, CX
        CMPQ    (AX), CX
        JNE     command-line-arguments_constPrefixInlined_pc35
        CMPB    8(AX), $101
        SETEQ   CL

What did you expect to see?

Same assembly output for constPrefixInlined and constPrefix.

Similar results exist for when the constant string is anywhere between 9 and 16 bytes inclusive. Strings 17 bytes and over output the same for both functions.

One other notable difference is that of the optimizations for non-power-of-two constant strings of length below 8 bytes, for example when const prefix = "1234567":

        CMPQ    BX, $7
        JLT     command-line-arguments_constPrefixInlined_pc40
        CMPL    (AX), $875770417
        JNE     command-line-arguments_constPrefixInlined_pc36
        CMPW    4(AX), $13877
        JNE     command-line-arguments_constPrefixInlined_pc36
        CMPB    6(AX), $55
        SETEQ   CL

and for the auto-inliner:

        CMPQ    BX, $7
        JLT     command-line-arguments_constPrefix_pc42
        MOVL    (AX), CX
        MOVL    3(AX), DX
        SHLQ    $32, DX
        ORQ     DX, CX
        MOVQ    $3978425819158753841, DX
        CMPQ    DX, CX
        SETEQ   CL

I'm not sure which of these two is better, but in any case I believe that they should agree on an approach.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performancecompiler/runtimeIssues related to the Go compiler and/or runtime.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions