compiler: do not emit nil checks for loading closure variables
Closure variables are allocated in a parent function and are thus never nil. Don't do a nil check before reading or modifying the value. This commit results in a slight reduction in code size in some test cases: calls.go, channel.go, goroutines.go, json.go, sort.go - presumably wherever closures are used.
Этот коммит содержится в:
родитель
ec325c0643
коммит
3edcdb5f0d
5 изменённых файлов: 14 добавлений и 21 удалений
|
@ -162,6 +162,10 @@ func (b *builder) createNilCheck(inst ssa.Value, ptr llvm.Value, blockPrefix str
|
||||||
case *ssa.Alloc:
|
case *ssa.Alloc:
|
||||||
// An alloc is never nil.
|
// An alloc is never nil.
|
||||||
return
|
return
|
||||||
|
case *ssa.FreeVar:
|
||||||
|
// A free variable is allocated in a parent function and is thus never
|
||||||
|
// nil.
|
||||||
|
return
|
||||||
case *ssa.IndexAddr:
|
case *ssa.IndexAddr:
|
||||||
// This pointer is the result of an index operation into a slice or
|
// This pointer is the result of an index operation into a slice or
|
||||||
// array. Such slices/arrays are already bounds checked so the pointer
|
// array. Such slices/arrays are already bounds checked so the pointer
|
||||||
|
|
|
@ -994,6 +994,8 @@ func getPos(val posser) token.Pos {
|
||||||
switch val := val.(type) {
|
switch val := val.(type) {
|
||||||
case *ssa.MakeInterface:
|
case *ssa.MakeInterface:
|
||||||
return getPos(val.X)
|
return getPos(val.X)
|
||||||
|
case *ssa.MakeClosure:
|
||||||
|
return val.Fn.(*ssa.Function).Pos()
|
||||||
case *ssa.Return:
|
case *ssa.Return:
|
||||||
syntax := val.Parent().Syntax()
|
syntax := val.Parent().Syntax()
|
||||||
if syntax != nil {
|
if syntax != nil {
|
||||||
|
|
10
compiler/testdata/goroutine-cortex-m-qemu.ll
предоставленный
10
compiler/testdata/goroutine-cortex-m-qemu.ll
предоставленный
|
@ -86,14 +86,6 @@ entry:
|
||||||
|
|
||||||
define hidden void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context, i8* %parentHandle) unnamed_addr {
|
define hidden void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq i8* %context, null
|
|
||||||
br i1 %0, label %store.throw, label %store.next
|
|
||||||
|
|
||||||
store.throw: ; preds = %entry
|
|
||||||
call void @runtime.nilPanic(i8* undef, i8* null)
|
|
||||||
unreachable
|
|
||||||
|
|
||||||
store.next: ; preds = %entry
|
|
||||||
%unpack.ptr = bitcast i8* %context to i32*
|
%unpack.ptr = bitcast i8* %context to i32*
|
||||||
store i32 7, i32* %unpack.ptr, align 4
|
store i32 7, i32* %unpack.ptr, align 4
|
||||||
ret void
|
ret void
|
||||||
|
@ -112,8 +104,6 @@ entry:
|
||||||
|
|
||||||
declare void @runtime.printint32(i32, i8*, i8*)
|
declare void @runtime.printint32(i32, i8*, i8*)
|
||||||
|
|
||||||
declare void @runtime.nilPanic(i8*, i8*)
|
|
||||||
|
|
||||||
define hidden void @main.funcGoroutine(i8* %fn.context, void (i32, i8*, i8*)* %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr {
|
define hidden void @main.funcGoroutine(i8* %fn.context, void (i32, i8*, i8*)* %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i8* @runtime.alloc(i32 12, i8* undef, i8* null)
|
%0 = call i8* @runtime.alloc(i32 12, i8* undef, i8* null)
|
||||||
|
|
10
compiler/testdata/goroutine-wasm.ll
предоставленный
10
compiler/testdata/goroutine-wasm.ll
предоставленный
|
@ -62,14 +62,6 @@ entry:
|
||||||
|
|
||||||
define hidden void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context, i8* %parentHandle) unnamed_addr {
|
define hidden void @"main.closureFunctionGoroutine$1"(i32 %x, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
entry:
|
entry:
|
||||||
%0 = icmp eq i8* %context, null
|
|
||||||
br i1 %0, label %store.throw, label %store.next
|
|
||||||
|
|
||||||
store.throw: ; preds = %entry
|
|
||||||
call void @runtime.nilPanic(i8* undef, i8* null)
|
|
||||||
unreachable
|
|
||||||
|
|
||||||
store.next: ; preds = %entry
|
|
||||||
%unpack.ptr = bitcast i8* %context to i32*
|
%unpack.ptr = bitcast i8* %context to i32*
|
||||||
store i32 7, i32* %unpack.ptr, align 4
|
store i32 7, i32* %unpack.ptr, align 4
|
||||||
ret void
|
ret void
|
||||||
|
@ -77,8 +69,6 @@ store.next: ; preds = %entry
|
||||||
|
|
||||||
declare void @runtime.printint32(i32, i8*, i8*)
|
declare void @runtime.printint32(i32, i8*, i8*)
|
||||||
|
|
||||||
declare void @runtime.nilPanic(i8*, i8*)
|
|
||||||
|
|
||||||
define hidden void @main.funcGoroutine(i8* %fn.context, i32 %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr {
|
define hidden void @main.funcGoroutine(i8* %fn.context, i32 %fn.funcptr, i8* %context, i8* %parentHandle) unnamed_addr {
|
||||||
entry:
|
entry:
|
||||||
%0 = call i32 @runtime.getFuncPtr(i8* %fn.context, i32 %fn.funcptr, i8* nonnull @"reflect/types.funcid:func:{basic:int}{}", i8* undef, i8* null)
|
%0 = call i32 @runtime.getFuncPtr(i8* %fn.context, i32 %fn.funcptr, i8* nonnull @"reflect/types.funcid:func:{basic:int}{}", i8* undef, i8* null)
|
||||||
|
|
9
transform/testdata/allocs2.go
предоставленный
9
transform/testdata/allocs2.go
предоставленный
|
@ -33,7 +33,7 @@ func main() {
|
||||||
c1 := getComplex128() // OUT: object allocated on the heap: escapes at line 34
|
c1 := getComplex128() // OUT: object allocated on the heap: escapes at line 34
|
||||||
useInterface(c1)
|
useInterface(c1)
|
||||||
|
|
||||||
n3 := 5 // OUT: object allocated on the heap: escapes at line 39
|
n3 := 5
|
||||||
func() int {
|
func() int {
|
||||||
return n3
|
return n3
|
||||||
}()
|
}()
|
||||||
|
@ -42,6 +42,13 @@ func main() {
|
||||||
|
|
||||||
s8 := []int{3, 5, 8} // OUT: object allocated on the heap: escapes at line 44
|
s8 := []int{3, 5, 8} // OUT: object allocated on the heap: escapes at line 44
|
||||||
callVariadic(s8...)
|
callVariadic(s8...)
|
||||||
|
|
||||||
|
n4 := 3 // OUT: object allocated on the heap: escapes at line 48
|
||||||
|
n5 := 7 // OUT: object allocated on the heap: escapes at line 48
|
||||||
|
func() {
|
||||||
|
n4 = n5
|
||||||
|
}()
|
||||||
|
println(n4, n5)
|
||||||
}
|
}
|
||||||
|
|
||||||
func derefInt(x *int) int {
|
func derefInt(x *int) int {
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче