• Philip Hofer's avatar
    cmd/compile: de-virtualize interface calls · 4e0c7c3f
    Philip Hofer authored
    With this change, code like
    
        h := sha1.New()
        h.Write(buf)
        sum := h.Sum()
    
    gets compiled into static calls rather than
    interface calls, because the compiler is able
    to prove that 'h' is really a *sha1.digest.
    
    The InterCall re-write rule hits a few dozen times
    during make.bash, and hundreds of times during all.bash.
    
    The most common pattern identified by the compiler
    is a constructor like
    
        func New() Interface { return &impl{...} }
    
    where the constructor gets inlined into the caller,
    and the result is used immediately. Examples include
    {sha1,md5,crc32,crc64,...}.New, base64.NewEncoder,
    base64.NewDecoder, errors.New, net.Pipe, and so on.
    
    Some existing benchmarks that change on darwin/amd64:
    
    Crc64/ISO4KB-8        2.67µs ± 1%    2.66µs ± 0%  -0.36%  (p=0.015 n=10+10)
    Crc64/ISO1KB-8         694ns ± 0%     690ns ± 1%  -0.59%  (p=0.001 n=10+10)
    Adler32KB-8            473ns ± 1%     471ns ± 0%  -0.39%  (p=0.010 n=10+9)
    
    On architectures like amd64, the reduction in code size
    appears to contribute more to benchmark improvements than just
    removing the indirect call, since that branch gets predicted
    accurately when called in a loop.
    
    Updates #19361
    
    Change-Id: Ia9d30afdd5f6b4d38d38b14b88f308acae8ce7ed
    Reviewed-on: https://go-review.googlesource.com/37751
    Run-TryBot: Philip Hofer <phofer@umich.edu>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: default avatarKeith Randall <khr@golang.org>
    4e0c7c3f
devirt.go 1.2 KB