gollvm: add attributes for some functions to help optimization
Teach the backend some facts about some runtime functions, to
help optimizations.
Change-Id: I7bca0f98042e45f87c91eab556c2e0e62a64d65f
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/183839
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/bridge/go-llvm.cpp b/bridge/go-llvm.cpp
index bc18b97..6daf115 100644
--- a/bridge/go-llvm.cpp
+++ b/bridge/go-llvm.cpp
@@ -55,6 +55,7 @@
, noInline_(false)
, noFpElim_(false)
, useSplitStack_(true)
+ , compilingRuntime_(false)
, checkIntegrity_(true)
, createDebugMetaData_(true)
, exportDataStarted_(false)
@@ -2658,6 +2659,73 @@
if (isGCLeaf(fns))
fcn->addFnAttr("gc-leaf-function");
+ // attributes about runtime functions, to help the optimizer
+ if (fns == "runtime.newobject" ||
+ fns == "runtime.makeslice" ||
+ fns == "runtime.makeslice64" ||
+ fns == "runtime.makechan" ||
+ fns == "runtime.makechan64") {
+ fcn->addAttribute(llvm::AttributeList::ReturnIndex,
+ llvm::Attribute::NonNull);
+ fcn->addAttribute(llvm::AttributeList::ReturnIndex,
+ llvm::Attribute::NoAlias);
+ }
+
+ // makemap may return its argument, so not noalias.
+ if (fns == "runtime.makemap" ||
+ fns == "runtime.makemap64" ||
+ fns == "runtime.makemap_small")
+ fcn->addAttribute(llvm::AttributeList::ReturnIndex,
+ llvm::Attribute::NonNull);
+
+ // mapaccess1 and mapassign never return nil.
+ if (fns == "runtime.mapaccess1" ||
+ fns == "runtime.mapaccess1_fast32" ||
+ fns == "runtime.mapaccess1_fast64" ||
+ fns == "runtime.mapaccess1_faststr" ||
+ fns == "runtime.mapaccess1_fat" ||
+ fns == "runtime.mapassign" ||
+ fns == "runtime.mapassign_fast32" ||
+ fns == "runtime.mapassign_fast64" ||
+ fns == "runtime.mapassign_fast32ptr" ||
+ fns == "runtime.mapassign_fast64ptr" ||
+ fns == "runtime.mapassign_faststr")
+ fcn->addAttribute(llvm::AttributeList::ReturnIndex,
+ llvm::Attribute::NonNull);
+
+ // mapaccess is pure function.
+ if (!compilingRuntime_ &&
+ (fns == "runtime.mapaccess1" ||
+ fns == "runtime.mapaccess1_fast32" ||
+ fns == "runtime.mapaccess1_fast64" ||
+ fns == "runtime.mapaccess1_faststr" ||
+ fns == "runtime.mapaccess1_fat" ||
+ fns == "runtime.mapaccess2" ||
+ fns == "runtime.mapaccess2_fast32" ||
+ fns == "runtime.mapaccess2_fast64" ||
+ fns == "runtime.mapaccess2_faststr" ||
+ fns == "runtime.mapaccess2_fat"))
+ fcn->addFnAttr(llvm::Attribute::ReadOnly);
+
+ // memcmp-like.
+ if (fns == "runtime.memequal" ||
+ fns == "runtime.cmpstring") {
+ fcn->addFnAttr(llvm::Attribute::ReadOnly);
+ fcn->addFnAttr(llvm::Attribute::ArgMemOnly);
+ }
+
+ if (fns == "runtime.memclrNoHeapPointers")
+ fcn->addFnAttr(llvm::Attribute::ArgMemOnly);
+
+ // These functions are called in unlikely branches. But they
+ // themselves are not actually cold in the runtime. So only
+ // mark cold when we are not compiling the runtime.
+ if (!compilingRuntime_ &&
+ (fns == "runtime.gcWriteBarrier" ||
+ fns == "runtime.typedmemmove" ||
+ fns == "runtime.growslice"))
+ fcn->addFnAttr(llvm::Attribute::Cold);
+
fcnValue = fcn;
// Fix up references to declaration of old type.
diff --git a/bridge/go-llvm.h b/bridge/go-llvm.h
index 2a73e9e..0d4824b 100644
--- a/bridge/go-llvm.h
+++ b/bridge/go-llvm.h
@@ -387,20 +387,23 @@
unsigned traceLevel() const { return traceLevel_; }
// Disable inlining if set to true.
- void setNoInline(bool b) { noInline_ = b; };
+ void setNoInline(bool b) { noInline_ = b; }
// Disable frame pointer elimination if set to true.
- void setNoFpElim(bool b) { noFpElim_ = b; };
+ void setNoFpElim(bool b) { noFpElim_ = b; }
// Enable/disable the use of split stacks.
- void setUseSplitStack(bool b) { useSplitStack_ = b; };
+ void setUseSplitStack(bool b) { useSplitStack_ = b; }
// Target CPU and features
void setTargetCpuAttr(const std::string &cpu);
void setTargetFeaturesAttr(const std::string &attrs);
// Set GC strategy
- void setGCStrategy(std::string s) { gcStrategy_ = s; };
+ void setGCStrategy(std::string s) { gcStrategy_ = s; }
+
+ // Whether we are compiling the runtime package
+ void setCompilingRuntime() { compilingRuntime_ = true; }
// Personality function
llvm::Function *personalityFunction();
@@ -753,6 +756,9 @@
// Whether to use split stacks.
bool useSplitStack_;
+ // Whether we are compiling the runtime.
+ bool compilingRuntime_;
+
// Whether to check for unexpected node sharing (e.g. same Bexpression
// or statement pointed to by multiple parents).
bool checkIntegrity_;
diff --git a/driver/CompileGo.cpp b/driver/CompileGo.cpp
index d6c3b8f..14ff429 100644
--- a/driver/CompileGo.cpp
+++ b/driver/CompileGo.cpp
@@ -692,6 +692,9 @@
args.backend = bridge_.get();
go_create_gogo (&args);
+ if (args.compiling_runtime)
+ bridge_->setCompilingRuntime();
+
/* The default precision for floating point numbers. This is used
for floating point constants with abstract type. This may
eventually be controllable by a command line option. */