From dcffbc49c4ed919f3d41556e9d56d3f50784f069 Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Sun, 7 Apr 2019 16:36:14 +0200 Subject: [PATCH] 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. --- compiler/compiler.go | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/compiler/compiler.go b/compiler/compiler.go index 3ed910c5..b19765de 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 {