diff --git a/compiler/symbol.go b/compiler/symbol.go index 6455fb8f..6eec892d 100644 --- a/compiler/symbol.go +++ b/compiler/symbol.go @@ -139,6 +139,17 @@ func (c *compilerContext) getFunction(fn *ssa.Function) llvm.Value { for _, attrName := range []string{"noalias", "nonnull"} { llvmFn.AddAttributeAtIndex(0, c.ctx.CreateEnumAttribute(llvm.AttributeKindID(attrName), 0)) } + case "runtime.sliceAppend": + // Appending a slice will only read the to-be-appended slice, it won't + // be modified. + llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("nocapture"), 0)) + llvmFn.AddAttributeAtIndex(2, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("readonly"), 0)) + case "runtime.sliceCopy": + // Copying a slice won't capture any of the parameters. + llvmFn.AddAttributeAtIndex(1, c.ctx.CreateEnumAttribute(llvm.AttributeKindID("writeonly"), 0)) + 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.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/compiler/testdata/slice.ll b/compiler/testdata/slice.ll index 3502851d..0cc5f8a6 100644 --- a/compiler/testdata/slice.ll +++ b/compiler/testdata/slice.ll @@ -60,7 +60,7 @@ entry: ret { i32*, i32, i32 } %7 } -declare { i8*, i32, i32 } @runtime.sliceAppend(i8*, i8*, i32, i32, i32, i32, i8*, i8*) +declare { i8*, i32, i32 } @runtime.sliceAppend(i8*, i8* nocapture readonly, i32, i32, i32, i32, i8*, i8*) define hidden { i32*, i32, i32 } @main.sliceAppendSlice(i32* %ints.data, i32 %ints.len, i32 %ints.cap, i32* %added.data, i32 %added.len, i32 %added.cap, i8* %context, i8* %parentHandle) unnamed_addr { entry: @@ -85,4 +85,4 @@ entry: ret i32 %copy.n } -declare i32 @runtime.sliceCopy(i8*, i8*, i32, i32, i32, i8*, i8*) +declare i32 @runtime.sliceCopy(i8* nocapture writeonly, i8* nocapture readonly, i32, i32, i32, i8*, i8*) diff --git a/transform/testdata/allocs2.go b/transform/testdata/allocs2.go index f01ad167..3e1df07d 100644 --- a/transform/testdata/allocs2.go +++ b/transform/testdata/allocs2.go @@ -22,6 +22,13 @@ func main() { s4 := make([]byte, 300) // OUT: object allocated on the heap: object size 300 exceeds maximum stack allocation size 256 readByteSlice(s4) + + s5 := make([]int, 4) // OUT: object allocated on the heap: escapes at line 27 + s5 = append(s5, 5) + + s6 := make([]int, 3) + s7 := []int{1, 2, 3} + copySlice(s6, s7) } func derefInt(x *int) int { @@ -45,3 +52,7 @@ func returnIntSlice(s []int) []int { } func getUnknownNumber() int + +func copySlice(out, in []int) { + copy(out, in) +}