Skip to content

cmd/compile: missed devirtualization #51554

@CAFxX

Description

@CAFxX

In the following snippet, the compiler should be able to devirtualize the fi.Foo() call, but currently this does not happen (godbolt):

package main

import "fmt"

type foo struct{}

func (_ foo) Foo() { fmt.Println("Foo") }

func main() {
	f := foo{}
	switch fi := any(f).(type) {
	case interface{ Foo() }:
		fi.Foo()
	}
}

The example is obviously artificial, but this definitely occurs in real code: e.g. see the code generated by envoyproxy/protoc-gen-validate, e.g. https://github.com/envoyproxy/go-control-plane/blob/99c9ceb26c9d7bf1705833b7debdebe9ae67c0ae/envoy/data/tap/v2alpha/transport.pb.validate.go.

Another use case that will become increasingly important with generics in 1.18 is to distinguish1 between different types provided in type unions, e.g.:

func Foo[Bytes interface{ []byte | string }](b Bytes) string {
	switch any(b).(type) {
	case []byte:
		return "[]byte"
	case string:
		return "string"
	}
    return "<unknown>"
}

As above, this missed devirtualization opportunity currently prevents (godbolt) the compiler from statically deducing the correct branch at compile-time, and pruning the dead branches.

This is somewhat related to #38992 in that also in this specific case it would be beneficial to run inlining again after devirtualization. For example, in the first example above, inlining after devirtualization would open up significant inlining opportunities in case an embedded message does not have validation rules (in which case its Validate* functions would simply return nil, potentially allowing to prune whole branches of the validation call tree)

Footnotes

  1. AFAICT this wouldn't currently be possible if the type constraint includes approximation elements (~T); the example does not use approximation elements for this reason

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