compiler: optimize comparing interface values against nil

This is a very common case. Avoiding a runtime.interfaceEqual call leads
to a very big reduction in code size in some cases (while it doesn't
affect many other examples). A number of driver smoke tests are reduced
by about 4kB just with this optimization.

I found this issue while looking into automatically calculating the
required amount of stack space for goroutines. The
runtime.interfaceEqual function is recursive, so it is best avoided.
This commit is contained in:
Ayke van Laethem
2020-04-04 15:47:22 +02:00
committed by Ayke
parent f06d7d1bd6
commit 46345aade6
+13 -1
View File
@@ -2207,7 +2207,19 @@ func (b *builder) createBinOp(op token.Token, typ, ytyp types.Type, x, y llvm.Va
case *types.Interface:
switch op {
case token.EQL, token.NEQ: // ==, !=
result := b.createRuntimeCall("interfaceEqual", []llvm.Value{x, y}, "")
nilInterface := llvm.ConstNull(x.Type())
var result llvm.Value
if x == nilInterface || y == nilInterface {
// An interface value is compared against nil.
// This is a very common case and is easy to optimize: simply
// compare the typecodes (of which one is nil).
typecodeX := b.CreateExtractValue(x, 0, "")
typecodeY := b.CreateExtractValue(y, 0, "")
result = b.CreateICmp(llvm.IntEQ, typecodeX, typecodeY, "")
} else {
// Fall back to a full interface comparison.
result = b.createRuntimeCall("interfaceEqual", []llvm.Value{x, y}, "")
}
if op == token.NEQ {
result = b.CreateNot(result, "")
}