diff options
author | Ayke van Laethem <[email protected]> | 2019-04-07 16:36:14 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2019-04-11 09:16:10 +0200 |
commit | dcffbc49c4ed919f3d41556e9d56d3f50784f069 (patch) | |
tree | 981728945dd7304d9b132db20a274b8e6f820622 | |
parent | 6a2a587dffff29089aea2eba197ae61086acbc4f (diff) | |
download | tinygo-dcffbc49c4ed919f3d41556e9d56d3f50784f069.tar.gz tinygo-dcffbc49c4ed919f3d41556e9d56d3f50784f069.zip |
compiler: add param attrs to memmove and memcpy
Add nocapture, readonly, and writeonly to runtime.memmove and
runtime.memcpy where appropriate. This teaches LLVM some more
optimizations it may perform, leading to reduced .text size in some
cases.
-rw-r--r-- | compiler/compiler.go | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/compiler/compiler.go b/compiler/compiler.go index 3ed910c58..b19765de0 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -371,18 +371,33 @@ func (c *Compiler) Compile(mainPath string) error { c.mod.NamedFunction("runtime.activateTask").SetLinkage(llvm.ExternalLinkage) c.mod.NamedFunction("runtime.scheduler").SetLinkage(llvm.ExternalLinkage) + // Load some attributes + getAttr := func(attrName string) llvm.Attribute { + attrKind := llvm.AttributeKindID(attrName) + return c.ctx.CreateEnumAttribute(attrKind, 0) + } + nocapture := getAttr("nocapture") + writeonly := getAttr("writeonly") + readonly := getAttr("readonly") + // Tell the optimizer that runtime.alloc is an allocator, meaning that it // returns values that are never null and never alias to an existing value. - for _, name := range []string{"noalias", "nonnull"} { - attrKind := llvm.AttributeKindID(name) - attr := c.ctx.CreateEnumAttribute(attrKind, 0) - c.mod.NamedFunction("runtime.alloc").AddAttributeAtIndex(0, attr) + for _, attrName := range []string{"noalias", "nonnull"} { + c.mod.NamedFunction("runtime.alloc").AddAttributeAtIndex(0, getAttr(attrName)) } // See emitNilCheck in asserts.go. - attrKind := llvm.AttributeKindID("nocapture") - attr := c.ctx.CreateEnumAttribute(attrKind, 0) - c.mod.NamedFunction("runtime.isnil").AddAttributeAtIndex(1, attr) + c.mod.NamedFunction("runtime.isnil").AddAttributeAtIndex(1, nocapture) + + // Memory copy operations do not capture pointers, even though some weird + // pointer arithmetic is happening in the Go implementation. + for _, fnName := range []string{"runtime.memcpy", "runtime.memmove"} { + fn := c.mod.NamedFunction(fnName) + fn.AddAttributeAtIndex(1, nocapture) + fn.AddAttributeAtIndex(1, writeonly) + fn.AddAttributeAtIndex(2, nocapture) + fn.AddAttributeAtIndex(2, readonly) + } // see: https://reviews.llvm.org/D18355 if c.Debug { |