From f868045f2ac6a5fdf74f12a1f1dac722241b8596 Mon Sep 17 00:00:00 2001 From: Damian Gryski Date: Fri, 18 Oct 2024 08:00:42 -0700 Subject: [PATCH 1/2] compiler: mark stringFromBytes as nocapture/readonly to help escape analysis Fixes #4525 --- compiler/symbol.go | 3 +++ transform/testdata/allocs2.go | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/compiler/symbol.go b/compiler/symbol.go index c2007cfd41..5447e0dba8 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -172,6 +172,9 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0)) llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) + case "runtime.stringFromBytes": + llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) + llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0)) case "runtime.trackPointer": // This function is necessary for tracking pointers on the stack in a // portable way (see gc_stack_portable.go). Indicate to the optimizer diff --git a/transform/testdata/allocs2.go b/transform/testdata/allocs2.go index 3b08fbc9e4..13c460231d 100644 --- a/transform/testdata/allocs2.go +++ b/transform/testdata/allocs2.go @@ -49,6 +49,11 @@ func main() { n4 = n5 }() println(n4, n5) + + // This shouldn't escape. + var buf [32]byte + s := string(buf[:]) + println(len(s)) } func derefInt(x *int) int { From 52662c4a69df2466d80f70e26da8bdf7a7af7425 Mon Sep 17 00:00:00 2001 From: Damian Gryski Date: Fri, 18 Oct 2024 12:17:38 -0700 Subject: [PATCH 2/2] compiler: mark stringFromRunes as nocapture/readonly --- compiler/symbol.go | 3 +++ transform/testdata/allocs2.go | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/compiler/symbol.go b/compiler/symbol.go index 5447e0dba8..e175bdd78d 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -175,6 +175,9 @@ func (c *compilerContext) getFunction(fn *ssa.Function) (llvm.Type, llvm.Value) case "runtime.stringFromBytes": llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0)) + case "runtime.stringFromRunes": + llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) + llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0)) case "runtime.trackPointer": // This function is necessary for tracking pointers on the stack in a // portable way (see gc_stack_portable.go). Indicate to the optimizer diff --git a/transform/testdata/allocs2.go b/transform/testdata/allocs2.go index 13c460231d..299df5b213 100644 --- a/transform/testdata/allocs2.go +++ b/transform/testdata/allocs2.go @@ -54,6 +54,10 @@ func main() { var buf [32]byte s := string(buf[:]) println(len(s)) + + var rbuf [5]rune + s = string(rbuf[:]) + println(s) } func derefInt(x *int) int {