diff options
author | Ayke van Laethem <[email protected]> | 2021-04-22 14:24:22 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2021-04-22 19:53:42 +0200 |
commit | 80caf2dab2523d1d6ff2a0716fd5fc3c83821074 (patch) | |
tree | 8762ae7db8ad5b1cc5bae6771838ec059b37ea93 | |
parent | c466465c32240f4db2feb35288025d2f7d4c410d (diff) | |
download | tinygo-80caf2dab2523d1d6ff2a0716fd5fc3c83821074.tar.gz tinygo-80caf2dab2523d1d6ff2a0716fd5fc3c83821074.zip |
copiler: add function attributes to some runtime calls
This allows better escape analysis even without being able to see the
entire program. This makes the stack allocation test case more complete
but probably won't have much of an effect outside of that (as the
compiler is able to infer these attributes in the whole-program
functionattrs pass).
-rw-r--r-- | compiler/symbol.go | 11 | ||||
-rw-r--r-- | compiler/testdata/slice.ll | 4 | ||||
-rw-r--r-- | transform/testdata/allocs2.go | 11 |
3 files changed, 24 insertions, 2 deletions
diff --git a/compiler/symbol.go b/compiler/symbol.go index 6455fb8f3..6eec892dd 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 3502851d4..0cc5f8a67 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 f01ad167c..3e1df07df 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) +} |