aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2021-04-22 14:24:22 +0200
committerRon Evans <[email protected]>2021-04-22 19:53:42 +0200
commit80caf2dab2523d1d6ff2a0716fd5fc3c83821074 (patch)
tree8762ae7db8ad5b1cc5bae6771838ec059b37ea93
parentc466465c32240f4db2feb35288025d2f7d4c410d (diff)
downloadtinygo-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.go11
-rw-r--r--compiler/testdata/slice.ll4
-rw-r--r--transform/testdata/allocs2.go11
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)
+}