mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 10:37:46 +00:00
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:
+13
-1
@@ -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, "")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user